/*****************************************************************************/
/*!	\file		IEC61850Types.h
 *	\brief		IEC 61580 API definition file
 *	\par		Dalian Yunxing Tech Co., Ltd.
 *
 *				Dalian, China
 *				Phone   : +86 (411) 8825 4852
 *				Email   : yx@yunxing.tech
 */
/*****************************************************************************/

#ifndef IEC61580TYPE_H
#define IEC61580TYPE_H	1

#include "sysctype.h"
#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

/*! 对象名称最大长度 */
#define OBJECT_NAME_STRING_LEN 64

/*! 对象引用最大长度 */
#define OBJECT_REFERENCE_STRING_LEN 129

/*! 功能约束字符串的长度 */
#define FC_LEN 2

/*! 控制块引用的最大长度 */
#define CB_REFNAME_SIZE 129

/*! 数据集的引用的最大长度 */
#define DATASET_NAME_SIZE 129
#define CDC_STRING_LEN   8
#define VISIBLE_STRING_129_LEN 129
#define VISIBLE_STRING_255_LEN 255
#define OBJECT_CERTIFICATE_STRING_LEN 8192

/*! \brief  数据属性句柄 */
typedef void* DAHANDLE;
/*! \brief  控制块句柄 */
typedef void* CBHANDLE;
/*! \brief  数据集句柄 */
typedef void* DATASETHANDLE;

#ifndef BITS_TO_BYTES
#define BITS_TO_BYTES(bitSize)		(((bitSize) + 7) / 8)		/*!< Converts size in bits to size in bytes, rounding up to the nearest byte */
#endif

/*!
	\defgroup	ServerCallback			服务端回调函数
	\defgroup	ClientCallback			客户端回调函数
	\defgroup	ServerAndClientCallback	服务端和客户端回调函数
*/

/*! \brief IEC61850_ErrorCode
 * 	\par YX-PIS 协议栈内部使用的错误码，其中以 `IEC61850_ERROR_SCL` 开头的为模型文件内容错误。
 */
typedef enum IEC61850_ErrorCode
{
	IEC61850_ERROR_NONE									= 0,		/*!< 无错误 */
	IEC61850_ERROR_INVALID_PARAMETERS					= -1,		/*!< 参数无效 */
	IEC61850_ERROR_NO_MEMORY							= -2,		/*!< 内存不足 */
	IEC61850_ERROR_SCL_FILE_OPEN_FAILED					= -3,		/*!< 打开模型文件失败 */
	IEC61850_ERROR_SERVICE_FAILED						= -4,		/*!< 服务失败 */
	IEC61850_ERROR_SCL_SYNTAX_ERROR						= -5,		/*!< 模型文件语法错误 */
	IEC61850_ERROR_SCL_IO_ERROR							= -6,		/*!< 模型输入输出错误 */
	IEC61850_ERROR_SCL_NO_IED_CONNECTEDAP				= -7,		/*!< 模型中无IED接入点 */
	IEC61850_ERROR_TYPE_MISMATCH						= -8,		/*!< 类型不匹配 */
	IEC61850_ERROR_LICENCE_INVALID						= -9,		/*!< 许可证无效 */
	IEC61850_ERROR_DATA_ATTRIBUTE_ID_NOT_FOUND			= -10,		/*!< 数据属性ID不存在 */
	IEC61850_ERROR_DATA_ATTRIBUTE_ID_NO_CONNECTION		= -11,		/*!< 数据属性ID对应的数据属性无连接(不可控制) */
	IEC61850_ERROR_SCL_LN_TYPE_NOT_FOUND				= -12,		/*!< 未找到逻辑节点类型定义 */
	IEC61850_ERROR_SCL_DATASET_NOT_FOUND				= -13,		/*!< 未找到数据集定义 */
	IEC61850_ERROR_SCL_GSE_COMM_NOT_FOUND				= -14,		/*!< 未找到GSE控制块对应的通信信息定义 */
	IEC61850_ERROR_SCL_SV_COMM_NOT_FOUND				= -15,		/*!< 未找到采样值控制块对应的通信信息定义 */
	IEC61850_ERROR_SCL_INVALID_MAC_ADDRESS				= -16,		/*!< Mac地址无效 */
	IEC61850_ERROR_GOOSE_INIT_FAILED					= -17,		/*!< GOOSE控制块初始化失败 */
	IEC61850_ERROR_SV_INIT_FAILED						= -18,		/*!< 采样值控制块初始化失败 */
	IEC61850_ERROR_CMS_INIT_FAILED						= -19,		/*!< 服务初始化失败 */
	IEC61850_ERROR_SCL_DATA_TYPE_TEMPLATE_NAME			= -20,		/*!< 数据类型模板名称错误 */
	IEC61850_ERROR_SCL_DATA_TYPE_TEMPLATE_ID			= -21,		/*!< 数据类型模板ID错误 */
	IEC61850_ERROR_SCL_DATASET_NAME						= -22,		/*!< 数据集名称错误 */
	IEC61850_ERROR_SCL_IED_ELEMENT_NAME					= -23,		/*!< IED元素名称错误 */
	IEC61850_ERROR_SCL_COMM_NAME						= -24,		/*!< 通信部分的接入点名称错误 */
	IEC61850_ERROR_INVALID_STATE						= -25,		/*!< 无效状态 */
	IEC61850_ERROR_SCL_DATASET_FCDA_NOT_FOUND			= -26,		/*!< 数据集中没有FCDA元素 */
	IEC61850_ERROR_SCL_DUPLICATE_LD						= -27,		/*!< 逻辑设备重复 */
	IEC61850_ERROR_SCL_LD_NO_NAME						= -28,		/*!< 逻辑设备无名称 */
	IEC61850_ERROR_SCL_LD_NO_LNS						= -29,		/*!< 逻辑设备下无逻辑节点 */
	IEC61850_ERROR_SCL_DUPLICATE_LN						= -30,		/*!< 逻辑节点定义重复 */
	IEC61850_ERROR_SCL_DUPLICATE_DOTYPES				= -31,		/*!< 数据对象类型定义重复 */
	IEC61850_ERROR_SCL_DUPLICATE_DATYPES				= -32,		/*!< 数据属性类型定义重复 */
	IEC61850_ERROR_SCL_DUPLICATE_ENUMTYPE				= -33,		/*!< 枚举类型定义重复 */
	IEC61850_ERROR_SCL_DUPLICATE_LNTYPES				= -34,		/*!< 逻辑节点类型定义重复 */
	IEC61850_ERROR_SCL_DUPLICATE_LNTYPE_DO_NAME			= -35,		/*!< 逻辑节点类型中的数据对象名称重复 */
	IEC61850_ERROR_SCL_LNTYPE_DO_NO_NAME				= -36,		/*!< 逻辑节点内的数据对象无名称 */
	IEC61850_ERROR_SCL_LNTYPE_NO_DOS					= -37,		/*!< 逻辑节点内无数据对象 */
	IEC61850_ERROR_SCL_DUPLICATE_DOTYPE_DA_NAME			= -38,		/*!< 数据对象类型中的数据属性名称重复 */
	IEC61850_ERROR_SCL_DUPLICATE_DOTYPE_SDO_NAME		= -39,		/*!< 数据对象类型中的子数据对象名称重复 */
	IEC61850_ERROR_SCL_DUPLICATE_DATYPE_BDA_NAME		= -40,		/*!< 数据对象类型中的子数据属性名称重复 */
	IEC61850_ERROR_GOOSE_CONTROL_BLOCK_INVALID			= -41,		/*!< GOOSE控制块无效 */
	IEC61850_ERROR_SCL_DUPLICATE_DA_ID					= -42,		/*!< 存在重复的数据属性ID */
	IEC61850_ERROR_CONTROL_NOT_ACTIVE					= -43,		/*!< 控制不可用或非有效控制对象 */
	IEC61850_ERROR_SCL_CONTROL_MODEL_INVALID			= -44,		/*!< 控制模式无效 */
	IEC61850_ERROR_SCL_DAI_WITHOUT_DA_TYPE				= -45,		/*!< 数据属性实例无对应的数据属性类型定义 */
	IEC61850_ERROR_SCL_CLIENT_TOO_FEW_IEDS				= -46,		/*!< 客户端模型中的IED数量过少 */
	IEC61850_ERROR_SERVICE_UNSUPPORTED					= -47,		/*!< 服务不支持 */
	IEC61850_ERROR_SV_CONTROL_BLOCK_INVALID				= -48,		/*!< 采样值控制块无效 */
	IEC61850_ERROR_CMS_COCMS_FAILED						= -49,		/*!< 通信失败 */
	IEC61850_ERROR_CMS_SAP_FAILED						= -50,		/*!< 服务访问点创建失败 */
	IEC61850_ERROR_ARRAY_INDEX_INVALID					= -51,		/*!< 数组元素索引无效 */
	IEC61850_ERROR_OPERATIVE_TEST_CALLBACK_NOT_SET		= -52,		/*!< 运行测试回调未设置 */
	IEC61850_ERROR_OPERATE_CALLBACK_NOT_SET				= -53,		/*!< 操作回调未设置 */
	IEC61850_ERROR_SCL_INVALID_TRIGGER_CONDITION		= -54,		/*!< 触发条件无效 */
	IEC61850_ERROR_SCL_INVALID_REPORT_CONTROL_BLOCK		= -55,		/*!< 报告控制块无效 */
	IEC61850_ERROR_INVALID_IP_ADDRESS					= -56,		/*!< IP地址无效 */
	IEC61850_ERROR_SERVICE_REJECTED						= -57,		/*!< 服务被拒绝 */
	IEC61850_ERROR_EDITION1_OR_EDITION2_FLAG_NOT_SET	= -58,		/*!< 版本标志未设置 */
	IEC61850_ERROR_SCL_MISSING_DO_TYPE_MEMORY			= -59,		/*!< 数据对象类型存储缺失 */
	IEC61850_ERROR_ARRAY_UPDATE_FAILED					= -60,		/*!< 数组更新失败 */
	IEC61850_ERROR_BITLENGTH_MISMATCH					= -61,		/*!< 位长不匹配 */
	IEC61850_ERROR_SELECT_RESPONSE_INVALID				= -62,		/*!< 选择命令响应结果为无效 */
	IEC61850_ERROR_SELECT_CMS_FAILED					= -63,		/*!< 选择命令执行失败 */
	IEC61850_ERROR_GOOSE_DEINITIALIZE_FAILED			= -64,		/*!< GOOSE控制块取消初始化失败 */
	IEC61850_ERROR_CMS_DEINITIALIZE_FAILED				= -65,		/*!< 服务取消初始化失败 */
	IEC61850_ERROR_SAMPLED_VALUES_DEINITIALIZE_FAILED	= -66,		/*!< 采样值控制块取消初始化失败 */
	IEC61850_ERROR_REPORTING_DEINITIALIZE_FAILED		= -67,		/*!< 报告控制块取消初始化失败 */
	IEC61850_ERROR_CONTROLS_DEINITIALIZE_FAILED			= -68,		/*!< 控制服务取消初始化失败 */
	IEC61850_ERROR_CONTROL_BLOCK_DEINITIALIZE_FAILED	= -69,		/*!< 控制块取消初始化失败 */
	IEC61850_ERROR_LOGGING_DEINITIALIZE_FAILED			= -70,		/*!< 日志控制块取消初始化失败 */
	IEC61850_ERROR_FREE_DATA_FAILED						= -71,		/*!< 数据释放失败 */
	IEC61850_ERROR_MMS_OR_CMS_SERVICE_FAILED			= -72,		/*!< 服务启动失败 */
	IEC61850_ERROR_GOOSE_SERVICE_FAILED					= -73,		/*!< GOOSE服务失败 */
	IEC61850_ERROR_SAMPLED_VALUE_SERVICE_FAILED			= -74,		/*!< 采样值服务失败 */
	IEC61850_ERROR_LOGGING_SERVICE_FAILED				= -75,		/*!< 日志服务失败 */
	IEC61850_ERROR_SCL_NO_DAID							= -76,		/*!< 无数据属性ID */
	IEC61850_ERROR_FUNCTION_NOT_SUPPORTED				= -77,		/*!< 功能不支持 */
	IEC61850_ERROR_ENTRYID_SET_ON_URCB_CB				= -78,		/*!< 为非缓存报告控制块设置了EntryID可选域 */
	IEC61850_ERROR_CONTROL_REJECTED						= -79,		/*!< 控制被拒绝 */
	IEC61850_ERROR_SV_GOOSE_CONTROL_BLOCK_CONFLICT		= -80,		/*!< 采样值控制块和GOOSE控制块冲突 */
	IEC61850_ERROR_EXTREF_DAI_NOT_FOUND					= -81,		/*!< 外部链接的数据属性实例不存在 */
	IEC61850_ERROR_CMS_TIMEOUT							= -82,		/*!< 通信超时 */
	IEC61850_ERROR_CMS_FILE_ERROR						= -83,		/*!< 文件服务错误 */
	IEC61850_ERROR_FILE_SYSTEM_ERROR					= -84,		/*!< 文件系统错误 */
	IEC61850_ERROR_GOOSE_SUB_DISABLED					= -85,		/*!< GOOSE订阅被禁用 */
	IEC61850_ERROR_NO_CONTROLS_FOUND					= -86,		/*!< 无可控数据 */
	IEC61850_ERROR_ID_DOES_NOT_MATCH_ACTIVE_CONTROL		= -87,		/*!< 同一控制序列的控制命令的数据属性ID不匹配 */
	IEC61850_ERROR_INVALID_ORIGIN_IDENT_SIZE			= -88,		/*!< 发起者标识大小无效 */
	IEC61850_ERROR_UPDATE_FAILED_VALUE_NOT_SUPPORTED	= -89,		/*!< 因数据值不支持而更新失败 */
	IEC61850_ERROR_SCL_INVALID_FC						= -90,		/*!< 功能约束无效 */
	IEC61850_ERROR_SETTING_GROUP_CONTROL_EMPTY			= -91,		/*!< 定值组内无定值数据 */
	IEC61850_ERROR_SCL_CONTROL_DA_UNSUPORTED			= -92,		/*!< 用于控制命令的数据对象中包含不被支持的数据对象 */
	IEC61850_ERROR_DATASET_MAX_ATTRIBUTES				= -93,		/*!< 数据集中的FCDA数量超出最大限制 */
	IEC61850_ERROR_DATASET_MAX							= -94,		/*!< 数据集数量超出最大限制 */
	IEC61850_ERROR_SCL_MULTIPLE_DAIDS					= -95,		/*!< 同一数据属性有多个数据属性ID */
	IEC61850_ERROR_INFO_START_AT_INVALID				= -96,		/*!< 获取数据点的索引超出数据点总数 */
	IEC61850_ERROR_OBJECT_NON_EXISTENT					= -97,		/*!< 对象不存在 */
	IEC61850_ERROR_SCL_DUPLICATE_GOCB_ID				= -98,		/*!< GOOSE控制块的控制块ID重复 */
	IEC61850_ERROR_SCL_DUPLICATE_RPTCB_ID				= -99,		/*!< 报告控制块的控制块ID重复 */
	IEC61850_ERROR_SERVERAT_AP_NOT_FOUND				= -100,		/*!< ServerAt接入点不存在 */
	IEC61850_ERROR_SERVERAT_SAME_HAVE_GOOSE_SV_AP		= -101,		/*!< 同一个AP存在多个服务器,且该AP包含goose或sv */
} IEC61850_ErrorCode;

/*! 控制发起者标识最大长度 */
#define CONTROL_ORIGIN_IDENT_SIZE 64

#define CONTROL_TIME_SIZE 8

/*! 控制请求的发起者类别。orCat = OriginatorCatagory
与 IEC61850-7-3-2010（DL/T 860.73-2013）的 6.8 章节的 "发起者 Originator" 内容相对应 */
typedef enum eOriginatorCat
{
	ORCAT_NOT_SUPPORTED = 0,		/*!< orCat不被支持 */
	ORCAT_BAY_CONTROL = 1,			/*!< 间隔层 */
	ORCAT_STATION_CONTROL = 2,		/*!< 变电站层 */
	ORCAT_REMOTE_CONTROL = 3,		/*!< 变电站外<br>例如 CC（ControlCentre 控制中心）、NCC（NetworkCC 网络控制中心）的远程控制 */
	ORCAT_AUTOMATIC_BAY = 4,		/*!< 间隔层自动 */
	ORCAT_AUTOMATIC_STATION = 5,	/*!< 变电站层自动 */
	ORCAT_AUTOMATIC_REMOTE = 6,		/*!< 变电站外自动 */
	ORCAT_MAINTENANCE = 7,			/*!< 维护/服务工具 */
	ORCAT_PROCESS = 8,				/*!< 过程层<br>无视控制行为而出现的状态变位（如断路器外部跳闸或内部故障） */
} eOriginatorCat;

/*!	\brief	抽象通信服务接口类（ACSIClass）
对应的是 IEC61850-7-2:2010（DL/T 860.72-2013）的第 10.2.2.2.2 章节中定义的 "ACSIClass 抽象通信服务接口类" */
typedef enum IEC61850_ACSIClass
{
	ACSI_CLASS_RESERVED = 0,		/*!< 保留值（Reserved）。<b>禁止使用</b> */
	ACSI_CLASS_DATA_OBJECT = 1,		/*!< 数据对象（Data object） */
	ACSI_CLASS_DATA_SET = 2,		/*!< 数据集（DATA-SET） */
	ACSI_CLASS_BRCB = 3,			/*!< 缓存报告控制块（BRCB） */
	ACSI_CLASS_URCB = 4,			/*!< 非缓存报告控制块（URCB） */
	ACSI_CLASS_LCB = 5,				/*!< 日志控制块（LCB） */
	ACSI_CLASS_LOG = 6,				/*!< 日志（LOG） */
	ACSI_CLASS_SGCB = 7,			/*!< 定值组控制块（SGCB） */
	ACSI_CLASS_GoCB = 8,			/*!< GOOSE 控制块（GoCB） */
	ACSI_CLASS_MSVCB = 10,			/*!< 多播采样值控制块（MSVCB） */
} IEC61850_ACSIClass;

/*!	\brief	数据属性ID（DAID）<br>
虽然 DAID 的 5 个域的数据类型都是 unsigned int，但建议每个域的数值都设置在 0~65535 之间 */
typedef struct IEC61850_DataAttributeID
{
	unsigned int field1;	/*!< 数据属性ID 的第一个数据域（Field1）的值 */
	unsigned int field2;	/*!< 数据属性ID 的第二个数据域（Field2）的值 */
	unsigned int field3;	/*!< 数据属性ID 的第三个数据域（Field3）的值 */
	unsigned int field4;	/*!< 数据属性ID 的第四个数据域（Field4）的值 */
	unsigned int field5;	/*!< 数据属性ID 的第五个数据域（Field5）的值 */
} IEC61850_DataAttributeID;

/*! \brief	控制块类别<br>
 *	\details
 *	该枚举值在 `struct IEC61850_ControlBlockID` 中使用，用于标记带有数据上报性质的控制块的类别。<br>
 *	属于 YX-PIS 协议栈私有属性 "控制块ID（Control Block ID）" 的一部分。
 */
typedef enum eControlBlockType
{
	CONTROLBLOCK_GOOSE,		/*!< GOOSE 控制块 */
	CONTROLBLOCK_REPORT,	/*!< 报告控制块 */
	CONTROLBLOCK_LOG,		/*!< 日志控制块 */
	CONTROLBLOCK_SV,		/*!< 采样值控制块 */
} eControlBlockType;

/*!	\brief	控制块ID（Control Block ID），简称为 CBID。
 *	\details
 *	控制块ID 是 YX-PIS 协议栈特有的内容。用于映射模型中的控制块，便于以控制块整体为单位对控制块关联的数据做处理。
 *	控制块ID 实际由 4 个无符号整型的数据域（Field1~Field4）、以及一个控制块的索引号构成，四个数据域的值来源于模型文件中给控制块分配的 控制块ID 定义。（在建模时额外配置）。
 *	虽然 控制块ID 的 4 个域的数据类型都是 unsigned int，但建议每个域的数值都设置在 0~65535 之间。
 */
typedef struct IEC61850_ControlBlockID
{
	eControlBlockType	controlBlockType;	/*!< 控制块的类别 */
	U32 	field1;		/*!< 控制块ID 的第一个数据域（Field1）的值 */
	U32 	field2;		/*!< 控制块ID 的第二个数据域（Field2）的值 */
	U32 	field3;		/*!< 控制块ID 的第三个数据域（Field3）的值 */
	U32 	field4;		/*!< 控制块ID 的第四个数据域（Field4）的值 */
	U32 	index;		/*!< 控制块的索引值。<br>由控制块在模型中的定义顺序决定。<br>值从 0 开始，按顺序依次递增 1。 */
} IEC61850_ControlBlockID;

/*!	\brief	控制块句柄信息  */
typedef struct IEC61850_CBHandleInfo
{
	eControlBlockType	controlBlockType;	/*!< 控制块的类别 */
	CBHANDLE			handle;				/*!< 控制块的句柄 */
	U32					index;				/*!< 控制块实例的编号。<br>对于报告控制块，0 代表所有实例，1~99 依次代表报告控制块的实例 01~99<br>对于GOOSE控制块，值应固定为 0 */
} IEC61850_CBHandleInfo;

/*!	IEC61850 的数据类型<br>
 * 对应类型的解释可以参照 IEC61850-7-2:2010（DL/T 860.72-2013）的 6.1.1 章节。<br>
 */
typedef enum IEC61850_DataType
{
	IEC61850_DATATYPE_ERROR = 0,			/*!< #eServiceError 服务差错 */
	IEC61850_DATATYPE_BOOLEAN = 1,			/*!< BOOLEAN 布尔 */
	IEC61850_DATATYPE_INT8 = 2,				/*!< INT8 有符号整型 */
	IEC61850_DATATYPE_INT16 = 3,			/*!< INT16 有符号整型 */
	IEC61850_DATATYPE_INT32 = 4,			/*!< INT32 有符号整型 */
	IEC61850_DATATYPE_INT64 = 5,			/*!< INT64 有符号整型 */
	IEC61850_DATATYPE_INT8U = 6,			/*!< INT8U 无符号整型 */
	IEC61850_DATATYPE_INT16U = 7,			/*!< INT16U 无符号整型 */
	IEC61850_DATATYPE_INT32U = 8,			/*!< INT32U 无符号整型 */
	IEC61850_DATATYPE_FLOAT32 = 9,			/*!< FLOAT32 单精度浮点型 */
	IEC61850_DATATYPE_FLOAT64 = 10,			/*!< FLOAT64 双精度浮点型 */
	IEC61850_DATATYPE_ENUMERATED = 11,		/*!< ENUMERATED 枚举 */
	IEC61850_DATATYPE_CODED_ENUM = 12,		/*!< CODED ENUM 固定枚举(不可扩展) */
	IEC61850_DATATYPE_OCTET_STRING = 13,	/*!< OCTET STRING 八位组串 */
	IEC61850_DATATYPE_VISIBLE_STRING = 14,	/*!< VisibleString 可视字符串 */
	IEC61850_DATATYPE_UNICODE_STRING = 15,	/*!< UNICODE STRING Unicode字符串 */
	IEC61850_DATATYPE_TIMESTAMP = 16,		/*!< TimeStamp 时间戳 */
	IEC61850_DATATYPE_QUALITY = 17,			/*!< Quality 品质 #IEC61850_QualityFlag */
	IEC61850_DATATYPE_ARRAY = 18,			/*!< Array 数组 */
	IEC61850_DATATYPE_STRUCTURE = 19,		/*!< Structure 结构体 */
} IEC61850_DataType;

/*!	\brief	数据值。包含数据值对应的数据类型。用于保存某个数据属性以及其下所有层级的完整数据信息 */
typedef struct IEC61850_DataAttributeData
{
	unsigned char type;		/*!< 数据类型。<br>取值为 `enum IEC61850_DataType` 类型的枚举值之一。<br>若数据类型为数组或者结构体，则每个数组元素或结构体成员，都将是一个单独的 `IEC61850_DataAttributeData` 类型的数据。 */
	int arrayIndex;			/*!< 数组元素索引。<br>若当前数据属性为数组类型数据中的某个元素时，该值有效，值为当前数据对应的数组元素索引；否则该值无意义，值为 0。 */
	unsigned int bitLength;	/*!< 数据长度信息。其值的意义，因数据类型而异。<br>若数据类型是数组，则该值代表数组元素数量；<br>若数据类型是结构体，则代表结构体成员的数量；<br>若数据类型既不是数组也不是结构体，则该值代表对应数据类型所占的实际位（bit）数。（例如，INT32 类型数据大小为 32 bit，则该值对应为 32。） */
	void* pvData;			/*!< 数据值的指针。<br>该指针指向数据值所在的内存空间地址。<br>若数据类型为数组数据，则该指针指向一个包含 `bitLength` 个 `IEC61850_DataAttributeData` 类型的数组元素的数组的首地址；<br>若数据类型为结构体，则该指针指向一个由 `bitLength` 个连续的 `IEC61850_DataAttributeData` 类型的结构体成员数据所构成的内存空间的首地址；<br>若数据类型既不是数组，也不是结构体，则可以按照对应的数据类型对该地址解引用来获取数据值。 */
} IEC61850_DataAttributeData;

/*!	客户端与服务端的关联状态 */
typedef enum IEC61850_ServerStatusVal
{
	SERVER_STATUS_UNKNOWN		= 0,	/*!< 未知（初始状态） */
	SERVER_STATUS_CONNECTED		= 1,	/*!< 已连接，通信中 */
	SERVER_STATUS_DISCONNECTED	= 2,	/*!< 连接断开 */
	SERVER_STATUS_CONNECTING	= 3,	/*!< 连接中 */
	SERVER_STATUS_DISCONNECTING	= 4,	/*!< 断开连接中 */
} IEC61850_ServerStatusVal;

/*!	\brief	YX-PIS 协议栈内更新 Boolean 类型数据时使用的 Boolean 类型的 bit 长度。<br>
 *	区别于 IEC61850 传输 Boolean 类型数据时，对 Boolean 类型数据的实际编码长度（1 bit）。	
 */
#define IEC61850_BOOLEAN_BITSIZE	8

/*!	\brief	时间戳类型数据的 bit 长度
 *	\see IEC61850_TimeStamp
 */
#define IEC61850_TIMESTAMP_BITSIZE	64

/*!	\brief	IEC61850 时间戳
	\details
	\b 秒的整数：
	其值为 UTC 时间的秒级时间戳。

	\b 秒的小数：
	秒的小数是一个长度为 24 的 bit 位串（BIT STRING）数据，共占三个字节。<br>
	IEC61850 规范中，秒的小数的值，是使用这个位串的每个 bit 位，按以下方法计算得到的。<br>
	计算公式为：\f${\sum_{n=0}^{23} (b_n * 2^{-(n+1)})}\f$<br>

	其中，\f${n}\f$ 为每个 bit 位的序号。24 个 bit 位中，最高位的序号为 0，最低位的序号为 23，<br>
	\f${b_n}\f$ 为每个 bit 位的值：0 或者 1，<br>
	每个 bit 位所代表的数值为：\f${b_n * 2^{-(n+1)}}\f$，<br>
	秒的小数的值，为所有 24 个 bit 位所代表的数值的总和。即，每个被置为 1 的 bit 位所代表的数值的总和。<br>

	举个例子，假设秒的小数的三个字节的位串值（二进制）为： 10001000 01000100 00000010<br>
	该值中，序号为 0、4、9、13、22 的 bit 位被置为了 1，<br>
	因此秒的小数的值为 \f$2^{-1}\f$ + \f$2^{-5}\f$ + \f$2^{-10}\f$ + \f$2^{-14}\f$ + \f$2^{-23}\f$ = 0.5 + 0.03125 + 0.000976562 + 0.000061035 + 0.000000119 = 0.532287716

	\b 时间品质：
	时间品质是一个长度为 8 的 bit 位串（BIT STRING）数据，占一个字节。<br>
	对于位串数据来说，最高位为位 0，因此其最低位则为位 7。<br>
	这些位所代表的含义如下：

	| 位   | 含义                                    |
	| ---- | --------------------------------------- |
	| 0    | 闰秒已知（LeapSecondsKnown）            |
	| 1    | 时钟故障（ClockFailure）                |
	| 2    | 时钟未同步（ClockNotSynchronized）      |
	| 3~7  | "秒的小数" 的时间精确度（TimeAccuracy） |

	"秒的小数" 的时间精确度：

	| 时间品质 3~7 位的值 | 含义                             |
	| ------------------- | -------------------------------- |
	| 00000               | 0 位精度（相当于秒的小数值为 0） |
	| 00001               | 1 位精度（0.5 秒）               |
	| 00010               | 2 位精度（0.25 秒）              |
	| 00011               | 3 位精度（0.125 秒）             |
	| 00100~11000         | 数值所对应的整数位精度           |
	| 11001~11110         | 非法                             |
	| 11111               | 未规定                           |

	取时间品质的第 3~7 五个 bit 位的时间精确度的十进制整数值，记为 n，其数值代表的时间精确度则为 \f${2^{-n}}\f$ 秒。<br>
	0 ≤ n ≤ 24 时，时间精确度为对应的有效值；n = 31 代表时间精确度未规定；<br>
	其他的 n 值（25~30）因为其代表的时间精确度，不属于常规使用的时间精确度（超出了纳秒级范围），被视为非法值。<br>
	具体如下表：（关于时间性能等级，可参照 IEC61850-5-2013（DL/T 860.5））

	| n 值  | 时间精确度         | 时间性能等级    |
	| ----- | ------------------ | --------------- |
	| 0     | 1s                 | TL（\>10000μs） |
	| 1     | 0.5s               | TL（\>10000μs） |
	| 2     | 0.25s              | TL（\>10000μs） |
	| 3     | 0.125s             | TL（\>10000μs） |
	| 4     | 62.5ms             | TL（\>10000μs） |
	| 5     | 31.25ms            | TL（\>10000μs） |
	| 6     | 15.625ms           | TL（\>10000μs） |
	| 7     | 7.8125ms           | T0（10000μs）   |
	| 8     | 3.90625ms          | T0（10000μs）   |
	| 9     | 1.953125ms         | T0（10000μs）   |
	| 10    | 976.562μs（≈ 1ms） | T1（1000μs）    |
	| 11    | 488.281μs          | T1（1000μs）    |
	| 12    | 244.141μs          | T1（1000μs）    |
	| 13    | 122.070μs          | T1（1000μs）    |
	| 14    | 61.035μs           | T2（100μs）     |
	| 15    | 30.518μs           | T2（100μs）     |
	| 16    | 15.259μs           | T3（25μs）      |
	| 17    | 7.629μs            | T3（25μs）      |
	| 18    | 3.815μs            | T4（4μs）       |
	| 19    | 1.907μs            | T4（4μs）       |
	| 20    | 954ns              | T5（1μs）       |
	| 21    | 477ns              | T5（1μs）       |
	| 22    | 238ns              | T5（1μs）       |
	| 23    | 119ns              | T5（1μs）       |
	| 24    | 60ns               | T5（1μs）       |
	| 25~30 | 非法               | -               |
	| 31    | 未规定             | -               |
*/
typedef struct IEC61850_TimeStamp
{
	U32	seconds;			/*!< 秒的整数 */
	U32	fractionsOfSecond;	/*!< 秒的小数 + 时间品质。<br>最低一个字节（8 个 bit 位）用来表示时间品质，其余的三个字节（24 个 bit 位）用来表示秒的小数 */
} IEC61850_TimeStamp;

/*!	\brief	服务端的状态信息 */
typedef struct IEC61850_ServerStatus
{
	char* ipAddress;						/*!< IP 地址 */
	char* iedName;							/*!< IED 名称 */
	S32 OSErrorCode;						/*!< 系统错误码。用于保存系统级的错误信息 */
	IEC61850_ServerStatusVal isConnected;	/*!< 客户端与该服务端 IED 的连接状态 */
} IEC61850_ServerStatus;

/*!	\brief	服务端的状态信息列表 */
typedef struct IEC61850_ServerStatusArray
{
	IEC61850_ServerStatus* serverStatusArray;	/*!< 服务端的状态信息列表。<br>信息源自客户端模型文件中所引用的服务端 IED 模型。<br>内容为 `IEC61850_ServerStatus` 的数组，数组元素数量由 `ServerStatusArraySize` 指定 */
	int serverStatusArraySize;					/*!< `serverStatusArray` 中 `IEC61850_ServerStatus` 元素的数量 */
} IEC61850_ServerStatusArray;

/*!  IEC61850 Quality flags. (see IEC 61850-8-1:2004 section 8.2)  */
typedef enum IEC61850_TimeQualityFlag
{
	IEC61850_TIMEQUALITY_LEAP_SECOND_KNOWN		= 0x0000000080,	/*!< Leap second known flag */
	IEC61850_TIMEQUALITY_CLOCK_FAILURE			= 0x0000000040,	/*!< Clock failure flag */
	IEC61850_TIMEQUALITY_CLOCK_NOT_SYNCHRONIZED	= 0x0000000020,	/*!< Clock not synchronised flag */
	IEC61850_TIMEQUALITY_0_BIT_OF_ACCURACY		= 0x0000000000,	/*!< 0 bit accuracy flag */
	IEC61850_TIMEQUALITY_1_BIT_OF_ACCURACY		= 0x0000000001,	/*!< 1 bit accuracy flag */
	IEC61850_TIMEQUALITY_24_BIT_OF_ACCURACY		= 0x0000000018,	/*!< 24 bit accuracy flag */
	IEC61850_TIMEQUALITY_ACCURACY_UNSPECIFIED	= 0x000000001F,	/*!< Accuracy unspecified flag */
} IEC61850_TimeQualityFlag;

/*!	\brief	品质（quality）类型数据的 bit 长度 */
#define IEC61850_QUALITY_BITSIZE	13

/*!	\brief	品质（quality）作为长度固定为 13 bit 的位串数据，在 YX-PIS 协议栈中，使用一个 U16（INT16U） 的数据来处理。<br>
品质数据的定义，可以参照 IEC61850-7-3-2010（DL/T 860.73-2013）的 6.2 章节。<br>
协议栈内通过 INT16U 数据来处理品质数据时，使用 `enum IEC61850_QualityFlag`。( #IEC61850_QualityFlag) */
typedef U16 tIEC61850Quality;

/*!	\typedef	IEC61850_QualityFlag
	\brief	品质（Quality）数据位标记
	\details
	用 INT16U 类型的数据来设置或解析 13 bit 的品质（quality）位串数据的枚举值定义。<br>
	用于在 `IEC61850_DataAttributeData` 中设置或解析品质数据。<br>
	其每个枚举值，代表品质数据中对应一个到两个 bit 位的意义。涉及多个品质 bit 位时，互为 或运算（`|`）的关系。<br>
	<br>
	INT16U 作为（网络大端序）位串数据的前 13 bit，代表实际的品质数据值。<br>
	其中，0~1 的前两个 bit 位整体代表品质的有效性（validity），这两个 bit 位是品质的主要数据值；<br>
	2~9 的每个 bit 位，各代表一种详细品质（detailQual）属性；<br>
	第 10 个 bit 位代表品质的数据源（source）属性，<br>
	由于该 bit 位代表数据源是 `process` 时的 bit 值为 0，0 与任意值做或（`|`）运算无必要，因此仅定义了该 bit 代表数据源是 `substituted` （bit 值为 1）时的枚举值；<br>
	第 11、12 两个 bit 位依次代表品质的 测试（test） 和 操作员闭锁（operatorBlocked）属性。<br>
	<br>
	由于 INT16U 的数据长度为 2 字节，因此值会涉及到大小端序的差异，<br>
	定义中将区分小端序和大端序的枚举值，使用时，请使用枚举名称。<br>
	在客户端服务端通信交互的数据包中，该数据值将被转换为网络大端序的位串来处理。<br>
	<br>
	关于品质数据的描述，可参照 IEC 61850-7-3:2010（DL/T 860.73-2013）的 6.2 章节。<br>
	关于品质数据的 MMS 映射，可参照 IEC 61850-8-1:2011 的 8.2 章节。
*/
typedef enum IEC61850_QualityFlag
{
#ifdef __BIGENDIAN__	// big-endian
	IEC61850_QUALITY_GOOD				= 0x0000,	/*!< Good */
	IEC61850_QUALITY_INVALID			= 0x4000,	/*!< Invalid */
	IEC61850_QUALITY_RESERVED			= 0x8000,	/*!< Reserved */
	IEC61850_QUALITY_QUESTIONABLE		= 0xC000,	/*!< Questionable */
	IEC61850_QUALITY_OVERFLOW			= 0x2000,	/*!< Overflow */
	IEC61850_QUALITY_OUTOFRANGE			= 0x1000,	/*!< Out of Range */
	IEC61850_QUALITY_BADREFERENCE		= 0x0800,	/*!< Bad Reference */
	IEC61850_QUALITY_OSCILLATORY		= 0x0400,	/*!< Oscillatory */
	IEC61850_QUALITY_FAILURE			= 0x0200,	/*!< Failure */
	IEC61850_QUALITY_OLDDATA			= 0x0100,	/*!< Old Data */
	IEC61850_QUALITY_INCONSISTENT		= 0x0080,	/*!< Inconsistent */
	IEC61850_QUALITY_INACCURATE			= 0x0040,	/*!< Inaccurate */
	IEC61850_QUALITY_SUBSTITUTED		= 0x0020,	/*!< Substituted if not set then Source is from the process */
	IEC61850_QUALITY_TEST				= 0x0010,	/*!< Test */
	IEC61850_QUALITY_OPERATOR_BLOCKED	= 0x0008,	/*!< Blocked by Operator */
	IEC61850_QUALITY_SV_DER				= 0x0004,	/*!< Derived Quality for Sampled Values ONLY, Der field is an identifier of the derived current sampled value. Der should be set when the value is calculated and not a measurement */
#else	// little-endian
	IEC61850_QUALITY_GOOD				= 0x0000,	/*!< bit 0~1, validity   / Good */
	IEC61850_QUALITY_INVALID			= 0x0040,	/*!< bit 0~1, validity   / Invalid */
	IEC61850_QUALITY_RESERVED			= 0x0080,	/*!< bit 0~1, validity   / Reserved */
	IEC61850_QUALITY_QUESTIONABLE		= 0x00C0,	/*!< bit 0~1, validity   / Questionable */
	IEC61850_QUALITY_OVERFLOW			= 0x0020,	/*!< bit 2,   detailQual / Overflow */
	IEC61850_QUALITY_OUTOFRANGE			= 0x0010,	/*!< bit 3,   detailQual / Out of Range */
	IEC61850_QUALITY_BADREFERENCE		= 0x0008,	/*!< bit 4,   detailQual / Bad Reference */
	IEC61850_QUALITY_OSCILLATORY		= 0x0004,	/*!< bit 5,   detailQual / Oscillatory */
	IEC61850_QUALITY_FAILURE			= 0x0002,	/*!< bit 6,   detailQual / Failure */
	IEC61850_QUALITY_OLDDATA			= 0x0001,	/*!< bit 7,   detailQual / Old Data */
#if defined (__PARADIGM__) /* Need to typecast to int on BECK RTOS on 16bit SC1x3 CPU due to enums being stored in 16bit signed integer */
	IEC61850_QUALITY_INCONSISTENT		= (int)0x8000,	/*!< bit 8,   detailQual / Inconsistent */
#else
	IEC61850_QUALITY_INCONSISTENT		= 0x8000,	/*!< bit 8,   detailQual / Inconsistent */
#endif
	IEC61850_QUALITY_INACCURATE			= 0x4000,	/*!< bit 9,   detailQual / Inaccurate */
	IEC61850_QUALITY_SUBSTITUTED		= 0x2000,	/*!< bit 10,  source     / Substituted if not set then Source is from the process */
	IEC61850_QUALITY_TEST				= 0x1000,	/*!< bit 11,  test       / Test */
	IEC61850_QUALITY_OPERATOR_BLOCKED	= 0x0800,	/*!< bit 12,  operatorBlocked / Blocked by Operator */
	IEC61850_QUALITY_SV_DER				= 0x0400,	/*!< Derived Quality for Sampled Values ONLY, Der field is an identifier of the derived current sampled value. Der should be set when the value is calculated and not a measurement - defined in 9-2LE*/
#endif	// (#ifdef __BIGENDIAN__)
} IEC61850_QualityFlag;

/*!	\brief	YX-PIS 协议栈内用于截取品质（quality）数据中的有效性（validity）部分的值（good \| invalid \| reserved \| questionable）的掩码。<br>
 *	用于结合 `enum IEC61850_QualityFlag` 使用，以从用 INT16U 数据类型保存的品质数据中，<br>
 *	提取出主要代表数据品质的 validity 部分的值，过滤掉品质数据中 detailQual、test、operatorBlocked 的数据部分。
 */
#ifdef __BIGENDIAN__
	#define IEC61850_QUALITY_BITMASK_VALIDITY 0xC000	// big-endian
#else
	#define IEC61850_QUALITY_BITMASK_VALIDITY 0x00C0	// little-endian
#endif	// of (#ifndef __BIGENDIAN__)

/*! \brief  用于设置或解析 RCB 选项域(OptFlds) 位串数据的枚举值
	\details
	用 INT16U 类型的数据来设置或解析 10 bit 的报告控制块可选域（OptFlds）位串数据的枚举值定义。<br>
	用于在 `SetBRCBValues`、`SetURCBValues` 中设置报告控制块的可选域，以及在 `BRCBValues`、`URCBValues` 中解析报告控制块的可选域。<br>
	其每个枚举值，都代表一个对应 bit 位的意义。涉及多个可选域 bit 位时，互为 或运算（`|`）的关系。<br>
	<br>
	INT16U 作为（网络大端序）位串数据的前 10 bit，代表实际报告控制块可选域的数据值。<br>
	由于 INT16U 的数据长度为 2 字节，因此值会涉及到大小端序的差异，<br>
	定义中将区分小端序和大端序的枚举值，使用时，请使用枚举名称。<br>
	在客户端服务端通信交互的数据包中，该数据值将被转换为网络大端序的位串来处理。<br>
*/
typedef enum IEC61850_ReportOption
{
#ifdef __BIGENDIAN__	// big-endian
	IEC61850_REPORT_OPTIONAL_RESERVED = 0x8000,				/*!< 保留 */
	IEC61850_REPORT_OPTIONAL_SEQUENCE_NUMBER = 0x4000,		/*!< 序列号 */
	IEC61850_REPORT_OPTIONAL_REPORT_TIME_STAMP = 0x2000,	/*!< 报告时标 */
	IEC61850_REPORT_OPTIONAL_REASON_FOR_INCLUSION = 0x1000,	/*!< 包含原因 */
	IEC61850_REPORT_OPTIONAL_DATA_SET_NAME = 0x0800,		/*!< 数据集名称 */
	IEC61850_REPORT_OPTIONAL_DATA_REFERENCE = 0x0400,		/*!< 数据引用 */
	IEC61850_REPORT_OPTIONAL_BUFFER_OVERFLOW = 0x0200,		/*!< 缓存区溢出 */
	IEC61850_REPORT_OPTIONAL_ENTRY_ID = 0x0100,				/*!< 条目标识 */
	IEC61850_REPORT_OPTIONAL_CONF_REVISION = 0x0080,		/*!< 配置版本 */
	IEC61850_REPORT_OPTIONAL_SEGMENTATION = 0x0040,			/*!< 分段 */
#else	// little-endian
	IEC61850_REPORT_OPTIONAL_RESERVED = 0x0080,				/*!< 保留（reserved）。<br>该 bit 位应始终为 0，禁止设置。  */
	IEC61850_REPORT_OPTIONAL_SEQUENCE_NUMBER = 0x0040,		/*!< 时序号（sequence-number）  */
	IEC61850_REPORT_OPTIONAL_REPORT_TIME_STAMP = 0x0020,	/*!< 时间戳（report-time-stamp）  */
	IEC61850_REPORT_OPTIONAL_REASON_FOR_INCLUSION = 0x0010,	/*!< 原因码（reason-for-inclusion） */
	IEC61850_REPORT_OPTIONAL_DATA_SET_NAME = 0x0008,		/*!< 数据集名称（data-set-name） */
	IEC61850_REPORT_OPTIONAL_DATA_REFERENCE = 0x0004,		/*!< 数据引用（data-reference） */
	IEC61850_REPORT_OPTIONAL_BUFFER_OVERFLOW = 0x0002,		/*!< 缓存溢出标记（buffer-overflow） */
	IEC61850_REPORT_OPTIONAL_ENTRY_ID = 0x0001,				/*!< 条目ID（entryID）  */
	IEC61850_REPORT_OPTIONAL_CONF_REVISION = 0x8000,		/*!< 配置版本号（conf-revision）  */
	IEC61850_REPORT_OPTIONAL_SEGMENTATION = 0x4000,			/*!< 分段（segmentation）。<br>该 bit 位应始终为 0，禁止设置。 */
#endif	// (#ifdef __BIGENDIAN__)
} IEC61850_ReportOption;

typedef enum IEC61850TriggerOption
{
	IEC61850_TRIGGER_OPTIONS_RESERVED			= 0x80,	/*!< 保留 (reserved) */
	IEC61850_TRIGGER_OPTIONS_DATA_CHANGE		= 0x40,	/*!< 数据改变 (dchg) */
	IEC61850_TRIGGER_OPTIONS_QUATLITY_CHANGE	= 0x20,	/*!< 品质改变 (qchg) */
	IEC61850_TRIGGER_OPTIONS_DATA_UPDATE		= 0x10,	/*!< 数据更新 (dupd) */
	IEC61850_TRIGGER_OPTIONS_INTEGRITY			= 0x08,	/*!< 完整性 (integrity) */
	IEC61850_TRIGGER_OPTIONS_GI					= 0x04,	/*!< 总召唤 (general-interrogation) */
} IEC61850TriggerOption;

/*!	\brief	YX-PIS 协议栈内更新 ENUMERATED 类型数据时使用的 ENUMERATED 类型的 bit 长度 */
#define IEC61850_ENUM_BITSIZE	8

/*!	\brief	IEC61850 Enumerated data type. (as specified in IEC61850_DATATYPE_ENUMERATED or IEC61850_DATATYPE_CODED_ENUM) */
typedef U8 tIEC61850Enum;

/*!	\brief	双点位置（Dbpos）类型在 IEC61850 中定义为 CODED ENUM 类型，即，实际是一个 2 bit 长度的位串数据。（同 `enum eDbPosValues` ）。
在协议栈中，双点位置的位串数据值，通常在 `IEC61850_DataAttributeData` 中，通过 INT8U 的数据类型来保存和解析。（同 `enum IEC61850DbPosValue`）。
*/
#define IEC61850_DATATYPE_DBPOS  IEC61850_DATATYPE_INT8U

/*!	\brief	YX-PIS 协议栈内使用 INT8U 数据来处理双点位置（Dbpos）数据时的数据类型 bit 长度。
该值用于在协议栈内通过 IEC61850_DataAttributeData 来更新双点位置数据时，标记数据的类型为双点位置（Dbpos）类型。
协议栈会依据此类型，来将 IEC61850_DataAttributeData 中通过 INT8U 类型保存的双点位置数据，
按照双点位置数据的实际长度（2 bit 的位串）来处理。	 
*/
#define IEC61850_DBPOS_BITSIZE	8

/*!	\brief	双点位置（Dbpos）。
	\details
	双点位置是一个 2bit 的位串数据。<br>
	该枚举值与 IEC61850 双点位置数据的定义一致。<br>
	<br>
	双点位置类型是 DPS、DPC 公共数据类的数据对象的状态值（stVal）的数据类型。<br>
	参照 IEC61850-7-3 中对 DPS、DPC 这两个公共数据类的定义，双点位置类型被定义为 CODED ENUM，实际上是一个 2 bit 长度的位串数据。<br>
	其取值为：`intermediate-state`、`off`、`on`、`bad-state`，其依次对应值： 0、1、2、3，即二进制的 `00`、`01`、`10`、`11`。<br>
	<br>
	在协议栈内，服务端要更新双点位置类型的数据时，应使用与双点位置定义相同的 `enum #eDbPosValues`。<br>
	特殊的，双点位置类型的数据更新触发客户端的数据更新回调时，数据更新回调函数中传入的双点位置数据，<br>
	是通过 INT8U 数据类型来保存的双点数据的位串，应使用 `enum IEC61850DbPosValue` 来解析，然后转换为相应的 `enum eDbPosValues`。 
*/
typedef enum eDbPosValues
{
	DBPOS_INTERMEDIATE = 0,	/*!< 00 中间状态（intermediate-state）  */
	DBPOS_OFF = 1,			/*!< 01 分闸（off） */
	DBPOS_ON = 2,			/*!< 10 合闸（on） */
	DBPOS_BAD = 3,			/*!< 11 故障状态（bad-state） */
} eDbPosValues;

/*!	双点位置（Dbpos）（2 bit）的位串数据用 INT8U 类型来保存时的数据值。
用于在协议栈内，通过 `IEC61850_DataAttributeData` 来设置或解析服务端客户端通信交互的双点位置数据。
其中，INT8U 作为位串数据使用时的前 2 bit （左边最高的 2 bit），代表实际的双点位置数据值。 */
typedef enum IEC61850DbPosValue
{
	IEC61850_DB_POS_OFF =	0x00,	/*!< 中间状态（intermediate-state） #DBPOS_INTERMEDIATE  */
	IEC61850_DB_POS_FALSE = 0x40,	/*!< 分闸（off） #DBPOS_OFF */
	IEC61850_DB_POS_TRUE =	0x80,	/*!< 合闸（on）  #DBPOS_ON */
	IEC61850_DB_POS_INVALID = 0xC0,	/*!< 故障状态（bad-state）  #DBPOS_BAD */
} IEC61850DbPosValue;

/*!	档位命令的枚举值 */
typedef enum eTcmdValue
{
	TCMD_STOP = 0,		/*!< stop  */
	TCMD_LOWER = 1,		/*!< lower */
	TCMD_HIGHER = 2,	/*!< higher */
	TCMD_RESERVED = 3	/*!< reserved */
} eTcmdValue;

/*!	the bit mask for resolving 'Tcmd' value in a byte */
typedef enum IEC61850TcmdValue
{
	IEC61850_TCMD_STOP = 0x00,		/*!< stop  */
	IEC61850_TCMD_LOWER = 0x40,		/*!< lower */
	IEC61850_TCMD_HIGHER = 0x80,	/*!< higher */
	IEC61850_TCMD_RESERVED = 0xC0	/*!< reserved */
} IEC61850TcmdValue;

/*!  行为模式（Mod、Beh）<br>
与 IEC61850-7-4-2010（DL/T 860.74-2014）的 "附录A" 的内容相对应。<br>
详细释义可以参照 IEC61850-7-4-2010（DL/T 860.74-2014）的 "附录A"。 */
typedef enum IEC61850_ModeAndBehaviourState
{
	IEC61850_MODE_ON = 1,			/*!< on */
	IEC61850_MODE_BLOCKED = 2,		/*!< on-blocked */
	IEC61850_MODE_TEST = 3,			/*!< test */
	IEC61850_MODE_TESTBLOCKED = 4,	/*!< test/blocked */
	IEC61850_MODE_OFF = 5,			/*!< off */
} IEC61850_ModeAndBehaviourState;

/*!    The states of Health (see 61850-7-4 IEC:2003 page 75) */
typedef enum IEC61850_HealthState
{
	IEC61850_HEALTH_OK = 1,		/*!< OK ("Green") No problems, normal operation   */
	IEC61850_HEALTH_WARNING = 2,		/*!< Warning (yellow minor problems, but in safe operation mode */
	IEC61850_HEALTH_ALARM = 3,		/*!< Alarm (red) severe problem, no operation possible */
} IEC61850_HealthState;

/*!	\brief	控制命令参数  */
typedef struct IEC61850_CommandParameter
{
	Boolean bTestMode;			/*!< 测试模式标记（Test） */
	S8 synchroCheck;			/*!< 同期检查标记（SynchroCheck） */
	S8 interlockCheck;			/*!< 互锁检查标记（Interlock-Check） */
	Boolean bStackGenerated;	/*!< 回调由内部堆栈条件触发标记<br>该成员会被 "取消回调函数" 使用。<br>（参照回调函数章节中对 IEC61850_ControlCancelCallback 的介绍） */
	enum eOriginatorCat orCat;	/*!< 发起者（orCat = Originator Catagory） */
	const char* orIdent;		/*!< 发起者标识（orIdent = Originator Identity） */
	U8 orIdentSize;				/*!< 发起者标识大小 */
	IEC61850_ModeAndBehaviourState localBeh; /*!< 行为模式状态 */
} IEC61850_CommandParameter;

struct IEC61850_Struct; /* IEC61850 对象类型。前置声明用。其实际定义无需用户关注。 */

/*!	\brief	IEC61850 对象类型。是个指针类型。
可由 `IEC61850_Create()` 接口创建并返回，并在其他 API 调用中作为必要的入参使用。
IEC61850 对象应作为全局变量定义使用。单个装置所使用的 IEC61850 对象应全局唯一。 */
typedef struct IEC61850_Struct* IEC61850;


/*!	\brief	用于个别回调函数的返回值。该枚举类型
其各个枚举值所代表的意义，与同名的 ServiceError 相同。
（ServiceError 为 IEC61850 协议规范中的错误码，其定义可参照 IEC61850-7-2:2010（DL/T 860.72-2013）的 6.1.2.6 章节） */
typedef enum IEC61850_CallbackReturnServiceErrorCode
{
	IEC61850_CB_ERROR_NONE = 0,									/*!< 无错误 */
	IEC61850_CB_ERROR_INSTANCE_NOT_AVAILABLE = -1,				/*!< 实例不可用 */
	IEC61850_CB_ERROR_ACCESS_VIOLATION = -2,					/*!< 访问违例 */
	IEC61850_CB_ERROR_PARAMETER_VALUE_INCONSISTENT = -3,		/*!< 参数值不一致 */
	IEC61850_CB_ERROR_INSTANCE_LOCKED_BY_OTHER_CLIENT = -4,		/*!< 实例被其他客户锁定 */
	IEC61850_CB_ERROR_TYPE_CONFLICT = -5,						/*!< 类型冲突 */
	IEC61850_CB_ERROR_FAILED_DUE_TO_SERVER_CONSTRAINT = -6,		/*!< 由于服务端约束失败 */
} IEC61850_CallbackReturnServiceErrorCode;

/*!	\brief	控制命令执行结果对应的附加原因码（AddCause）。用于控制服务。
	\details
	其类别与对应的解释，请参照 IEC61850-7-2-2010（DL/T 860.72-2013）的 20.5.2.9 章节的 "AddCause 附加的原因诊断" 内容。

	MMS 版本的 AddCause 类型与值的映射关系，可参照 IEC61850-8-1-2011（DL/T 860.81-2016）中第 20.11 章节的 "表97  ACSI 额外原因值的映射"
	CMS 版本与 MMS 版本相比，对调了其中最后两个枚举值的映射关系。即，在 CMS 版本中，locked-by-other-client=26，inconsistent-parameter=27。其他 AddCause 枚举值的映射关系与 MMS 版本的相同。

	其中 `IEC61850_COMMAND_ERROR_NONE` (-1) 为 YX-PIS 协议栈内部使用的枚举值，其余的枚举值的映射与 CMS 协议要求一致。
	应使用 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) 代表控制请求正常动作。

	大多数场合下，不需要用户主动决定控制命令响应的 AddCause，协议栈会自行判断决定。
	如需人为决定控制命令响应的 AddCause 的值（例如在 Operate 命令执行之前，运行测试不通过的场景下），也应参照 IEC61850 的协议要求，指定与实际控制状态机对应的、意义适当的 AddCause，不能随意指定。
*/
typedef enum eCommandAddCause
{
	IEC61850_COMMAND_ERROR_NONE = -1,										/*!< 无  */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_UNKNOWN = 0,							/*!< 未知 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_NOT_SUPPORTED = 1,						/*!< 不支持 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_BLOCKED_BY_SWITCHING_HIERARCHY = 2,	/*!< 被开关机构闭锁 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_SELECT_FAILED = 3,						/*!< 选择失败 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_INVALID_POSITION = 4,					/*!< 无效位置 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_POSITION_REACHED = 5,					/*!< 到达位置 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_PARAMETER_CHANGE_IN_EXECUTION = 6,		/*!< 执行中参数改变 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_STEP_LIMIT = 7,						/*!< 步长限制 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_BLOCKED_BY_MODE = 8,					/*!< 被模式闭锁 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_BLOCKED_BY_PROCESS = 9,				/*!< 被过程闭锁 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_BLOCKED_BY_INTERLOCKING = 10,			/*!< 被互锁闭锁 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_BLOCKED_BY_SYNCHROCHECK = 11,			/*!< 被检同期互锁 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_COMMAND_ALREADY_IN_EXECUTION = 12,		/*!< 命令已在执行中  */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_BLOCKED_BY_HEALTH = 13,				/*!< 被健康状态闭锁 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_1_OF_N_CONTROL = 14,					/*!< 1对N控制 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_ABORTION_BY_CANCEL = 15,				/*!< 因取消而异常终止 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_TIME_LIMIT_OVER = 16,					/*!< 超时 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_ABORTION_BY_TRIP = 17,					/*!< 因跳闸而异常终止 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_OBJECT_NOT_SELECTED = 18,				/*!< 对象没被选择 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_OBJECT_ALREADY_SELECTED = 19,			/*!< 对象已被选择 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_NO_ACCESS_AUTHORITY = 20,				/*!< 无访问权限 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_ENDED_WITH_OVERSHOOT = 21,				/*!< 因超调而结束 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_ABORTION_DUE_TO_DEVIATION = 22,		/*!< 因偏差而异常终止 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_ABORTION_BY_COMMUNICATION_LOSS = 23,	/*!< 因通信中断而异常终止 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_BLOCKED_BY_COMMAND = 24,				/*!< 因命令而闭锁 */
	IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE = 25,								/*!< 无 */
	IEC61850_COMMAND_ERROR_ADD_LOCKED_BY_OTHER_CLIENT = 26,					/*!< 被其他客户锁定 */
	IEC61850_COMMAND_ERROR_ADD_INCONSISTENT_PARAMETER = 27,					/*!< 参数不一致 */
} eCommandAddCause;

/*! \brief CMS数据类型定义 */
typedef enum eDataTypeCMS
{
	DATA_TYPE_ERROR = 0,			/*!< #eServiceError 服务差错 */
	DATA_TYPE_ARRAY = 1,			/*!< Array 数组 */
	DATA_TYPE_STRUCTURE = 2,		/*!< Structure 结构体 */
	DATA_TYPE_BOOLEAN = 3,			/*!< BOOLEAN 布尔 */
	DATA_TYPE_INT8 = 4,				/*!< INT8 有符号整型 */
	DATA_TYPE_INT16 = 5,			/*!< INT16 有符号整型 */
	DATA_TYPE_INT32 = 6,			/*!< INT32 有符号整型 */
	DATA_TYPE_INT64 = 7,			/*!< INT64 有符号整型 */
	DATA_TYPE_INT8U = 8,			/*!< INT8U 无符号整型 */
	DATA_TYPE_INT16U = 9,			/*!< INT16U 无符号整型 */
	DATA_TYPE_INT32U = 10,			/*!< INT32U 无符号整型 */
	DATA_TYPE_INT64U = 11,			/*!< INT64U 无符号整型 */
	DATA_TYPE_FLOAT32 = 12,			/*!< FLOAT32 单精度浮点型 */
	DATA_TYPE_FLOAT64 = 13,			/*!< FLOAT64 双精度浮点型 */
	DATA_TYPE_BIT_STRING = 14,		/*!< BIT STRING 位串 */
	DATA_TYPE_OCTET_STRING = 15,	/*!< OCTET STRING 八位组串 */
	DATA_TYPE_VISIBLE_STRING = 16,	/*!< VisibleString 可视字符串 */
	DATA_TYPE_UNICODE_STRING = 17,	/*!< UNICODE STRING Unicode字符串 */
	DATA_TYPE_UTC_TIME = 18,		/*!< UtcTime 协调世界时。实际为 OCTET STRING(SIZE(8))  */
	DATA_TYPE_BINARY_TIME = 19,		/*!< BinaryTime 二进制时间。实际为 OCTET STRING(SIZE(6))  */
	DATA_TYPE_QUALITY = 20,			/*!< Quality 品质。实际为 BIT STRING(SIZE(13))  */
	DATA_TYPE_DBPOS = 21,			/*!< Dbpos 双点位置。实际为 BIT STRING(SIZE(2))<br>二进制的值意义如下：<br>00：intermediate-state<br>01：off<br>10：on<br>11：bad-state */
	DATA_TYPE_TCMD = 22,			/*!< Tcmd 档位命令。实际为 BIT STRING(SIZE(2))<br>二进制的值意义如下：<br>00：stop<br>01：lower<br>10：higher<br>11：reserved */
	DATA_TYPE_CHECK = 23,			/*!< Check 检测。实际为 BIT STRING(SIZE(2))<br>位 0 代表同期检测（synchrocheck）<br>位 1 代表联锁检测（Interlock-check） */
} eDataTypeCMS;

/*! \brief   IEC61850 对象角色类型。服务端 或 客户端。  */
typedef enum IEC61850_ClientServerFlag
{
	IEC61850_SERVER = 0,		/*!< 服务端 */
	IEC61850_CLIENT = 1,		/*!< 客户端 */
} IEC61850_ClientServerFlag;

/*! \brief	IEC61850 对象版本  */
typedef enum IEC61850_Ed1_Ed2_Flag
{
	IEC61850_Edition1 = 0,	/*!< 版本一 */
	IEC61850_Edition2 = 1,	/*!< 版本二（通常使用该版本） */
} IEC61850_Ed1_Ed2_Flag;

/*! \brief	定值组数据的初始加载方式。<br>
	该枚举类型用于 IEC61850 对象的属性参数，用来指定服务端启动或重启时，定值组数据的初始加载动作。 
*/
typedef enum IEC61850_LoadSGDataFlag
{
	IEC61850_LOAD_LAST_SG_CHANGES = 0,	/*!< 加载为最后一次修改过的定值。<br>若从来没有或修改过定值组的定值，则与 IEC61850_IGNORE_SG_CHANGES 无差别 */
	IEC61850_IGNORE_SG_CHANGES = 1,		/*!< 无视定值的修改。<br>即，始终按照模型文件中的定义，来加载定值组。<br>包括初始激活的定值组号，以及该定值组号所对应的定值数据 */
}IEC61850_LoadSGDataFlag;

/*! \brief  IEC61850 对象的数据映射模式
	该枚举类型用于 IEC61850 对象属性参数的 "数据映射模式" 成员（dataMapMode）
*/
typedef enum IEC61850_DataMapMode
{
	IEC61850_MAP_MODE_DAID = 0,			/*!< 数据属性ID（DAID） */
	IEC61850_MAP_MODE_SADDR = 1,		/*!< 短地址（sAddr = Short Address） */
	IEC61850_MAP_MODE_REFERENCE = 2,	/*!< 引用（Reference） */
} IEC61850_DataMapMode;

/*! \brief  IEC61850 对象的可选参数。用于为创建的 IEC61850 对象添加额外属性。 */
typedef enum IEC61850_OptionFlag
{
	IEC61850_OPTION_NONE							= 0x00,		/*!< 无。是默认的 0 值。任何其他选项被设置，将覆盖并忽略该值 */
	IEC61850_OPTION_FLAG_TEST_MODE					= 0x01,		/*!< 设置服务器为测试模式（只用于内部测试用，不应由客户使用） */
	IEC61850_OPTION_BLOCK_WRITE_TO_CF				= 0x02,		/*!< 阻止对 FC=CF 数据的写操作。如果被设置，则不能对功能约束为 CF 的数据进行写操作（即，不能修改配置信息） */
	IEC61850_OPTION_SERVER_SEND_CONCLUDE_REQUEST	= 0x04,		/*!< **CMS 不适用。禁止使用** */
	IEC61850_OPTION_SERVER_SUBSCRIBE_GOOSE			= 0x08,		/*!< 允许服务端订阅 GOOSE 报文。由同时作为 GOOSE 订阅端的服务端使用 */
	IEC61850_OPTION_ALLOW_DUPLICATE_DAID			= 0x10,		/*!< **慎重使用** <br>允许包含重复 DAID 的模型文件被加载。<br>如果能够确保模型文件中不存在重复的 DAID，使用该选项可跳过模型加载时的 DAID 校重流程。<br>否则，使用该选项可能引起不可预见的结果。 */
	IEC61850_OPTION_UCA_TESTING						= 0x20,		/*!< **禁止使用** */
	IEC61850_OPTION_SLOW_LOAD						= 0x40,		/*!< **禁止使用** */
	IEC61850_OPTION_SYSTEMCORP_RESERVED				= 0x80,		/*!< **禁止使用** */
	IEC61850_OPTION_DEFAULT_INDEXED_REPORTING_FALSE	= 0x100,	/*!< 报告控制块默认indexed=false */
	IEC61850_OPTION_DISABLE_AUTO_FEEDBACK_CMD_TERM	= 0x200,	/*!< 取消增强安全控制流程的命令终止的自动反馈 */
	IEC61850_OPTION_DISABLE_CONTROL_CFDC_READ_ONLY	= 0x400,	/*!< 取消对控制模型中功能约束为 CF 和 DC 的数据的只读限制。<br>除非完全了解使用该选项可能导致的控制模型变化所产生的影响，否则不应使用。 */
	IEC61850_OPTION_ONLY_ALLOW_SE_EDITING			= 0x800,	/*!< 只允许编辑 CID 模型中 FC=SE 的定值数据。<br>使用该选项，模型中 FC=SG 的定值数据将不可编辑。 */
} IEC61850_OptionFlag;

/*! \brief 服务错误码（ServiceError）。
	\details
	服务错误的类型，参照 IEC61850-7-2:2010（DL/T 860.72-2013）中第 6.1.2.6 章节的 "ServiceError（服务差错）类型"。<br>
	MMS 版本对 ServiceError 类型与值的映射关系，参照 IEC61850-8-1-2011（DL/T 860.81-2016）中第 15.2 章节的 "表52  ACSI 服务错误值的映射"。<br>
	CMS 版本 ServiceError 值的映射与 MMS 版本的一致。
*/
typedef enum eServiceError
{
	SERVICE_ERROR_NO_ERROR = 0,								/*!< 无差错（no-error） */
	SERVICE_ERROR_INSTANCE_NOT_AVAILABLE = 1,				/*!< 实例不可用（instance-not-available） */
	SERVICE_ERROR_INSTANCE_IN_USE = 2,						/*!< 实例在使用（instance-in-use） */
	SERVICE_ERROR_ACCESS_VIOLATION = 3,						/*!< 访问违例（access-violation） */
	SERVICE_ERROR_ACCESS_NOT_ALLOWED_IN_CURRENT_STATE = 4,	/*!< 在当前状态不允许访问（access-not-allowed-in-current-state） */
	SERVICE_ERROR_PRARMETER_VALUE_INAPPROPRIATE = 5,		/*!< 参数值不合适（parameter-value-inappropriate） */
	SERVICE_ERROR_PARAMETER_VALUE_INCONSISTENT = 6,			/*!< 参数值不一致（parameter-value-inconsistent） */
	SERVICE_ERROR_CLASS_NOT_SUPPORTED = 7,					/*!< 类不被支持（class-not-supported） */
	SERVICE_ERROR_INSTANCE_LOCKED_BY_OTHER_CLIENT = 8,		/*!< 实例由其他客户端闭锁（instance-locked-by-other-client） */
	SERVICE_ERROR_CONTROL_MUST_BE_SELECTED = 9,				/*!< 控制前必须选择（control-must-be-selected） */
	SERVICE_ERROR_TYPE_CONFLICT = 10,						/*!< 类型冲突（type-conflict） */
	SERVICE_ERROR_FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT = 11, /*!< 由于通信约束失败（failed-due-to-communications-constraint） */
	SERVICE_ERROR_FAILED_DUE_TO_SERVER_CONSTRAIANT = 12		/*!< 由于服务器约束失败（failed-due-to-server-constraint） */
} eServiceError;

/*! \brief  文件名称最大长度。
因不同的操作系统对文件名或文件路径有不同的最大长度限制，256 仅是一个相对通用的参考值。
实际使用协议栈时，需要注意确保不要出现超过操作系统最大长度限制的文件名或文件目录长度。 
*/
#define IEC61850_FILENAME_SIZE			256

/*! \brief  广义的时间字符串最大长度 */
#define IEC61850_GENERALIZED_TIME_SIZE	30	

/*!	\brief	文件信息 */
typedef struct tFile
{
	char		fileName[IEC61850_FILENAME_SIZE];			 /*!< 文件名 */
	char		lastModified[IEC61850_GENERALIZED_TIME_SIZE];/*!< 最后的修改时间的字符串 格式: YYYYMMDDHHMMSShhmmss.fffZ */
	IEC61850_TimeStamp lastModifiedTime;					 /*!< 最后的修改时间 */
	U32			fileSize;									 /*!< 文件大小。单位为字节 */
	Boolean		bDirectory;									 /*!< 是否是文件夹<br>TRUE：文件夹<br>FALSE：文件 */
	Boolean		bHide;										 /*!< 是否为隐藏的文件或目录<br>TRUE：隐藏<br>FALSE：非隐藏 */
	U32			checkSum;									 /*!< 校验和<br>是文件数据的 CRC32 校验码，其生成多项式采用 0x04C11DB7 */
} tFile;

/*!	\brief	读文件目录的响应结果列表  */
typedef struct tFileList
{
	U32 length;		/*!< 读文件目录的响应结果数量 */
	tFile* files;	/*!< 读文件目录的响应结果列表。
						内容为 struct #tFile 的数组，元素数量由 u32FilesNum 成员指定 */
} tFileList;

/*!	\brief	文件属性 */
typedef struct tFileAttr
{
	tFile primaryFile;			/*!< 首要文件信息 */
	tFile* directoryEntries;	/*!< 文件目录条目集。<br>条目数量由 numOfDirectoryEntries 指定，需要遍历解析。 */
	U32 numOfDirectoryEntries;	/*!< 文件目录条目数量 */
} tFileAttr;

/*! \brief	客户端请求的文件服务调用类别 */
typedef enum IEC61850_FileCallType
{
	IEC61850_FILE_CALL_READ = 1,				/*!< 读文件 */
	IEC61850_FILE_CALL_GET_ATTRIBUTES = 2,		/*!< 获取文件属性 */
	IEC61850_FILE_CALL_DELETE = 3,				/*!< 删除文件 */
	IEC61850_FILE_CALL_SET_FILE = 4,			/*!< 写文件 */
	IEC61850_FILE_CALL_SET_FILE_COMPLETE = 5,	/*!< 写文件完成 */
	IEC61850_FILE_CALL_SET_FILE_FAIL = 6,		/*!< 写文件失败 */
} IEC61850_FileCallType;

/*! \brief		客户端请求的文件服务调用的响应码 */
typedef enum IEC61850_FileResponseCode
{
	IEC61850_FILE_RESPONSE_ACCEPT = 0,			/*!< 请求被接受 */
	IEC61850_FILE_RESPONSE_ACCESS_DENIED = 1,	/*!< 访问被拒绝 */
	IEC61850_FILE_RESPONSE_NON_EXISTENT = 2,	/*!< 文件不存在 */
} IEC61850_FileResponseCode;

/*! \brief		定值组操作类型 */
typedef enum IEC61850_SettingGroup_Operation
{
	SG_SELECT_ACTIVE	= 0,	/*!< 选择激活定值组 回调传参SGCallback_Select结构体 */
	SG_SELECT_EDIT		= 1,	/*!< 选择编辑定值组 回调传参SGCallback_Select结构体 */
	SG_CONFIRM_EDIT		= 2,	/*!< 确认编辑定值组 回调传参char*为定值组控制块引用 */
	SG_GET_VALUE		= 3,	/*!< 获取定值组值 回调传参SGCallback_Data结构体 */
	SG_SET_VALUE		= 4,	/*!< 设置定值组值 回调传参SGCallback_Data结构体 */
	SG_GET_SGCB			= 5,	/*!< 读定值组控制块值 回调传参char*为定值组控制块引用 */
} IEC61850_SettingGroup_Operation;

/*! \brief	定值组回调传递的参数结构体
用于选择激活或编辑定值组的回调。 */
typedef struct SGCallback_Select
{
	char* reference;	/*!< 定值组控制块引用 */
	U8 sgNumber;		/*!< 定值组的组号 */
} SGCallback_Select;

/*! \brief		定值组回调传递的参数结构体。
用于选择激活或编辑定值组的回调。 */
typedef struct SGCallback_Data
{
	char* reference;		/*!< 定值组数据引用 */
	char* fc;				/*!< 定值组数据的功能约束 */
	IEC61850_DataType type;	/*!< 定值组数据类型 \see #IEC61850_DataType  */
	unsigned int size;		/*!< 定值组数据值大小 */
	void* data;				/*!< 定值组数据值 */
} SGCallback_Data;

/*! \brief		对于增强安全的控制对象的操作命令的控制结果。
用于命令终止回调函数。 */
typedef struct ControlResult
{
	char reference[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 控制对象的引用 */
	IEC61850_DataAttributeData ctlVal;			/*!< 控制值 */
	U32		orCat;								/*!< 控制请求的发起者（orCat = Originator Catagory） */
	U8		orIdent[64];						/*!< 控制请求的发起者标识（orIdent = Originator Identity） */
	U8		ctlNum;								/*!< 控制请求编号 */
	IEC61850_TimeStamp  t;						/*!< 控制请求的时间戳 */
	Boolean	test;								/*!< 控制请求的测试（Test）标志 */
	U8		check;								/*!< 控制请求的检查（Check）标志 */
	IEC61850_TimeStamp* operTm;					/*!< 时间激活控制请求的时间。在 CommandTermination 请求中固定为 0 值 */
	eCommandAddCause eCtlAddCause;				/*!< 控制请求的附加的原因诊断（AddCause） */
} ControlResult;

/*!	\brief	写回调。
	\details
	该回调函数为服务端使用的回调函数，当前仅可由 激活定值 的动作触发。
	在服务端模型中配置了数据属性ID（DAID）的定值数据属性，将在以下场景下触发服务端执行写回调：
	- 服务端启动后初始化定值组配置时，执行的激活定值组动作；
	- 客户端请求的选择激活定值组（SelectActiveSG）请求被服务端成功执行时；
	- 因客户端成功确认编辑的定值组（ConfirmEditSGValues）与当前激活的定值组为同一组，而引发服务端执行的更新激活定值动作。

	其他写数据的动作暂不触发该回调函数。

	\ingroup 	ServerCallback

	\param[in]	userData	用户指定的数据指针
	\param[in]	dataMap		指向正在读取的数据属性ID的指针
	\param[in]	newValue	指向正在写入的值的指针。

	\return  成功返回 #IEC61850_CB_ERROR_NONE 失败返回 枚举 #IEC61850_CallbackReturnServiceErrorCode 中的相关值

	\see IEC61850_SetUserData()
*/
typedef IEC61850_CallbackReturnServiceErrorCode(*IEC61850_WriteCallback)(void* userData, const void* dataMap, const IEC61850_DataAttributeData* newValue);


/*!	\brief	数据更新回调
	\details
	该回调函数是数据订阅方触发的回调函数，用于从服务端发布的 报告、GOOSE、SV 中得知服务端的数据更新信息，进而触发和执行自己本地的期待动作（例如对比和同步本地数据）。
	数据订阅方通常是客户端，也可以是服务端。各有以下触发场景：

	- 数据订阅方为客户端：
		- 客户端接收到了服务端上送的报告；
		- 客户端作为 GOOSE 订阅端，接收到了所订阅的服务端发布的 GOOSE 消息；
		- 客户端作为 SV 订阅端，接收到了所订阅的服务端发布的 SV 消息。
	- 数据订阅方为服务端：
		- 服务端同时作为 GOOSE 订阅端，接收到了所订阅的服务端发布的 GOOSE 消息。

	报告、GOOSE 消息、SV 消息 中的每个数据会逐一触发该回调函数，
	`dataMap` 参数对应的是数据在数据订阅方模型中配置的数据属性映射信息，
	`newValue` 参数对应的是数据值。

	对于不同的触发数据源，该回调函数的动作和被调用的条件有所不同，详细如下：

	**报告触发**

	报告的接收方，固定为客户端。
	客户端接收到服务端上送的报告后，将在满足以下条件时调用该回调函数：

	1. 客户端的模型中，正确引用了与 \"报告数据\" 相匹配的服务端模型；
	2. 报告中的数据，在客户端引用的服务端模型中，配置有与 数据映射模式 匹配的 数据属性映射信息。
		即，需要满足以下匹配关系中的一种，才会触发回调函数：

		- 客户端的数据映射模式为 数据属性ID（ #IEC61850_MAP_MODE_DAID ），且报告对应的数据配置有 DAID；
			该种情况下，`dataMap` 参数传入的是数据的数据属性ID，对应的实际数据类型为 const IEC61850_DataAttributeID *。
		- 客户端的数据映射模式为 短地址（ #IEC61850_MAP_MODE_SADDR ），且报告对应的数据配置有 sAddr；
			该种情况下，`dataMap` 参数传入的是数据的短地址，对应的实际数据类型为 `const char*`。
		- 客户端的数据映射模式为 引用（ #IEC61850_MAP_MODE_REFERENCE ），（引用无需配置，不依赖额外的数据属性映射信息）。
			该种情况下，`dataMap` 参数传入的是数据的引用，对应的实际数据类型为 `const char*`。

		与客户端的 数据映射模式 相匹配的 数据属性映射信息 不存在时，报告不会触发该回调函数。

	**GOOSE 消息触发**

	GOOSE 订阅端可以是客户端，也可以是服务端。
	GOOSE 订阅端收到并处理 GOOSE 消息时，将在满足以下条件时，调用该回调函数：

	1. GOOSE 订阅端的模型中，正确引用了与 "订阅的 GOOSE 数据" 相匹配的 GOOSE 发布端（服务端）模型；
	2. GOOSE 订阅端收到的 GOOSE 消息，为需要处理的 GOOSE 消息，例如：
		- GOOSE 订阅端刚启动时首次收到的（每个订阅的 GOOSE 控制块上送的）的 GOOSE 消息；
		- 包含新事件（新 event）的 GOOSE 消息。（以常规 T0 间隔上送的 GOOSE 消息不会触发数据更新回调）
	3. GOOSE 消息中的数据，在 GOOSE 订阅端所引用的 GOOSE 发布端（服务端）模型中，配置有  DAID。
		未配置 DAID 的数据将不会触发回调。

	由 GOOSE 消息触发的数据更新回调，将无视 GOOSE 订阅端的数据映射模式。
	以上条件满足时，该回调函数将固定以数据属性ID（ #IEC61850_MAP_MODE_DAID ）的数据映射模式来回调，
	即，即使 GOOSE 订阅端的数据映射模式不是数据属性ID（ #IEC61850_MAP_MODE_DAID ），也会回调。
	回调时，`dataMap` 参数传入的数据属性映射信息固定为 DAID，对应的实际数据类型固定为 const IEC61850_DataAttributeID *。

	特殊的，
	若 GOOSE 订阅端为服务端，且订阅的 GOOSE 数据有被 Inputs 配置绑定了订阅端本地的数据，
	则该回调函数回调时，`dataMap` 参数将额外附带第二个 DAID：

	- 首个 DAID 不变，还是订阅端所引用的 GOOSE 发布端 模型中的 DAID；
	- 第二个 DAID，是由 Inputs 绑定的订阅端本地数据的 DAID。
		即，Inputs intAddr 指定的订阅端本地数据的 DAID。

	两个 DAID 只要有任意一个存在，回调函数就可以被触发。
	回调时，只有存在的 DAID 会有值。
	如果两个 DAID 都不存在，则不会触发回调。

	**SV 消息触发**

	SV 的订阅端，固定为客户端。
	客户端收到并处理 SV 消息时，将在满足以下条件时，调用该回调函数：

	1. 客户端的模型中，需要正确引用与 "订阅的 SV 数据" 相匹配的 SV 发布端（服务端）模型；
	2. SV 中的数据，在客户端所引用的 SV 发布端（服务端）模型中，配置有与 数据映射模式 匹配的 数据属性映射信息。
		客户端的数据映射模式为 数据属性ID（ #IEC61850_MAP_MODE_DAID ）或 短地址（ #IEC61850_MAP_MODE_SADDR ）时，SV 消息才会触发该回调函数。
		同时，需要保证数据属性映射信息存在，且与数据映射模式一致，
		即，满足以下匹配关系中的一种：

		- 客户端的数据映射模式为 数据属性ID（ #IEC61850_MAP_MODE_DAID ），且报告对应的数据配置有 DAID；
			该种情况下，`dataMap` 参数传入的是数据的数据属性ID，对应的实际数据类型为 const IEC61850_DataAttributeID *。
		- 客户端的数据映射模式为 短地址（ #IEC61850_MAP_MODE_SADDR ），且报告对应的数据配置有 sAddr；
			该种情况下，`dataMap` 参数传入的是数据的短地址，对应的实际数据类型为 `const char*`。

		与客户端的 数据映射模式 相匹配的 数据属性映射 信息不存在时，SV 消息不会触发该回调函数；
		客户端的数据映射模式为 引用（ #IEC61850_MAP_MODE_REFERENCE ）时，SV 消息也不会触发该回调函数。

	\ingroup	ServerAndClientCallback

	\param[in]	userData	自定义用户数据
	\param[in]	dataMap		数据属性映射。用于识别数据属性。<br>应基于回调方 IEC61850 对象的数据映射模式、角色、以及使用回调的场景，来确定 dataMap 传入的数据属性映射信息的类别，并按照相应的类别解析其值，以定位被更新数据的数据属性。
	\param[in]	newValue	数据发布方（服务端）更新的数据属性所对应数据的值。<br>通过 `dataMap` 确定触发回调的数据的数据属性。

	\return		none

	\see IEC61850_SetUserData()

	<b>示例</b>
	\code
	void UpdateCB(void* userData, const void* dataMap, const IEC61850_DataAttributeData* newValue)
	{
		// dataMap 对应的数据属性值更新为了 newValue。

		// 假设 dataMap 为 DAID，
		IEC61850_DataAttributeID* daid = (IEC61850_DataAttributeID*)dataMap;	// 转换 dataMap 为 DAID
		if ((daid->field1 == 0) && (daid->field2 == 1) && (daid->field3 == 2) &&
			(daid->field4 == 3) && (daid->field5 == 4)) {    // 确认 DAID 对应的数据属性
			// 假设 dataMap 对应的是一个 INT32 类型的数据属性
			S32 int32NewVal = 0;	// 定义一个 INT32 类型的数据，
			int32NewVal = (*((S32*)newValue->pvData));	// 接收 newValue 传入的新数据值。
			// ...
		}

		// 或者，
		// 假设 dataMap 为短地址（sAddr），
		// const char* sAddr = (const char*)dataMap;	// 转换 dataMap 为 char*
		// if (strcmp(sAddr, "sAddrExample") == 0) {	// 确认 sAddr 对应的数据属性
		// 	// ...
		// }

		// 或者，
		// 假设 dataMap 为引用（reference），
		// const char* reference = (const char*)dataMap;	// 转换 dataMap 为 char*
		// if (strcmp(reference, "LDName/LNName.DOName.DAName") == 0) {	// 	确认引用对应的属性
		// 	// ...
		// }
	}
	\endcode
*/
typedef void (*IEC61850_UpdateCallback)(void* userData, const void* dataMap, const IEC61850_DataAttributeData* newValue);


/*!	\brief	数据点品质可疑回调。
	\details
	用于通知 GOOSE 订阅端 GOOSE 数据的接收超时或中断，订阅端本地同步的 GOOSE 数据，应视为过期且品质可疑的数据。

	当 GOOSE 订阅端在 TAL（TimeAllowedToLive）时限内，没有接收到 GOOSE 发布端（服务端）重发的 GOOSE 消息时，该回调函数会在 GOOSE 订阅端被调用。触发回调的条件如下：

	1. GOOSE 订阅端的模型中，正确引用了与 \"订阅的 GOOSE 数据\" 相匹配的 GOOSE 发布端（服务端）的模型；
	2. GOOSE 消息中的数据，在 GOOSE 订阅端所引用的 GOOSE 发布端（服务端）模型中，配置有 DAID。

	该回调函数无视 GOOSE 订阅端的数据映射模式，将固定以数据属性ID（ #IEC61850_MAP_MODE_DAID ）的数据映射模式来触发回调，
	`dataMap` 参数对应的实际数据类型固定为 `const IEC61850_DataAttributeID*`。

	若 GOOSE 消息中的数据没有配置 DAID，则相应的 GOOSE 订阅数据不会触发该回调函数。

	\ingroup 	ServerAndClientCallback

	\param[in]	userData	自定义用户数据
	\param[in]	dataMap		数据属性映射。用于识别数据属性。<br>实际数据类型固定为 `const IEC61850_DataAttributeID*`。

	\return		none

	\see IEC61850_SetUserData()

	<b>示例</b>
	\code
	void DataPointQuestionableCB(void* userData, const void* dataMap)
	{
		// dataMap 所对应数据的品质可疑
	}
	\endcode
*/
typedef void (*IEC61850_DataPointQuestionableCallback)(void* userData, const void* dataMap);

/*!	\brief	操作前选择测试回调。
	\details
	用于控制服务。可用于处理 带值操作前选择（SelectWithValue）控制命令的选择测试（Select Test）。

	当客户端请求了操作前选择命令（例如调用了 `IEC61850_ControlSelect()` 接口），
	且选择的是 SBOes 控制对象（即，操作前选择命令是带值的 SelectWithValue）时，服务端会调用该回调函数。
	回调的前提是，服务端的模型中，有为控制对象的 \"状态值\" 配置有与数据映射模式一致的数据属性映射。

	返回值指定为 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) 代表选择测试通过（Test OK），后续的控制流程将继续处理。
	若该回调函数中无任何处理，应返回 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) ；
	返回值指定为 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) 以外的其他有效 AddCause 枚举值，将视为选择测试未通过（Test Not OK），
	对应的 SelectWithValue 请求将以指定的 AddCause 响应和动作。指定返回的 AddCause 应为适用于当下控制状态机的合理 AddCause。

	\ingroup 	ServerCallback

	\param[in]	userData				自定义用户数据
	\param[in]	dataMap					数据属性映射。用于识别控制对象。<br>
										数据映射模式为数据属性ID（ #IEC61850_MAP_MODE_DAID ）时，对应的是控制对象 \"状态值\" 的 DAID，对应的数据类型是 `IEC61850_DataAttributeID*`；<br>
										数据映射模式为短地址（ #IEC61850_MAP_MODE_SADDR ）时，对应的是控制对象 \"状态值\" 的 sAddr，对应的数据类型是 `char*`；<br>
										数据映射模式为引用（ #IEC61850_MAP_MODE_REFERENCE ）时，对应的是控制对象的引用，对应的数据类型是 `char*`。
	\param[in]	selectTestParameters	控制参数信息

	\return		成功返回 #IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE ，失败返回适当的 附加的原因诊断 #eCommandAddCause

	\see IEC61850_SetUserData()

	<b>示例</b>
	\code
	eCommandAddCause SelectTestCB(void* userData, const void* dataMap, const IEC61850_CommandParameter* selectTestParameters)
	{
		eCommandAddCause cmdAddCause = IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE;

		// 数据映射模式为数据属性ID（IEC61850_MAP_MODE_DAID）时，转换 dataMap 为 DAID
		IEC61850_DataAttributeID* daid = (IEC61850_DataAttributeID*)dataMap;
		IEC61850_PrintDataAttributeID(daid);	// 打印 DAID

		// 数据映射模式为短地址（IEC61850_MAP_MODE_SADDR）或引用（IEC61850_MAP_MODE_REFERENCE）时，转换 dataMap 为 char*
		// printf("sAddr(or reference) is: [%s]\n", (char*)dataMap);	// 打印 sAddr 或 reference

		if ((Boolean)selectTestParameters->synchroCheck) {
			Boolean synchroCheckOK = TRUE;
			synchroCheckOK = FALSE;
			// 执行同期检查 SynchroCheck
			if (!synchroCheckOK) {
				printf("SynchroCheck NG\n");
				return IEC61850_COMMAND_ERROR_ADD_CAUSE_BLOCKED_BY_SYNCHROCHECK;
			}
		}

		if ((Boolean)selectTestParameters->interlockCheck) {
			Boolean interlockCheckOK = TRUE;
			interlockCheckOK = FALSE;
			// 执行互锁检查 Interlock-Check
			if (!interlockCheckOK) {
				printf("Interlock-Check NG\n");
				return IEC61850_COMMAND_ERROR_ADD_CAUSE_BLOCKED_BY_INTERLOCKING;
			}
		}

		return cmdAddCause;
	}
	\endcode
*/
typedef eCommandAddCause (*IEC61850_ControlSelectTestCallback)(void* userData, const void* dataMap, const IEC61850_CommandParameter* selectTestParameters);

/*!	\brief	操作前选择回调。
	\details
	用于控制服务，可用于得知客户端请求了操作前选择 Select / SelectWithValue 控制命令。

	当客户端请求了 Select / SelectWithValue 操作前选择命令（例如调用了 `IEC61850_ControlSelect()` 接口）时，服务端将在选择测试通过之后，
	（即，选择测试回调函数 `IEC61850_ControlSelectTestCallback` 返回 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) 之后），在执行操作前选择动作之前调用该回调函数。
	回调的前提是，服务端的模型中，有为控制对象的 \"状态值\" 配置有与数据映射模式一致的数据属性映射。

	控制对象将在该该回调函数返回 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) 时被成功选择。

	建议把涉及拒绝操作前选择命令的情况，都放在该回调函数被调用之前的 `IEC61850_ControlSelectTestCallback` 回调函数中处理，
	该回调函数应始终返回 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) ，不应返回其他 AddCause。

	\ingroup 	ServerCallback

	\param[in]	userData			自定义用户数据
	\param[in]	dataMap				数据属性映射。用于识别控制对象。<br>
									数据映射模式为数据属性ID（ #IEC61850_MAP_MODE_DAID ）时，对应的是控制对象 \"状态值\" 的 DAID，对应的数据类型是 `IEC61850_DataAttributeID*`；<br>
									数据映射模式为短地址（ #IEC61850_MAP_MODE_SADDR ）时，对应的是控制对象 \"状态值\" 的 sAddr，对应的数据类型是 `char*`；<br>
									数据映射模式为引用（ #IEC61850_MAP_MODE_REFERENCE ）时，对应的是控制对象的引用，对应的数据类型是 `char*`。
	\param[in]	selectValue			操作前选择命令所附带的选择控制值。<br>
									对于选择 SBOes 控制对象的 SelectWithValue 命令，该值有效；<br>
									对于选择 SBOns 控制对象的 Select 命令，该值为 NULL。
	\param[in]	selectParameters	控制参数信息

	\return		成功返回 #IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE ，失败返回适当的 附加的原因诊断 #eCommandAddCause

	\see IEC61850_SetUserData()

	<b>示例</b>
	\code
	eCommandAddCause SelectCB(void* userData, const void* dataMap, const IEC61850_DataAttributeData* selectValue, const IEC61850_CommandParameter* selectParameters)
	{
		eCommandAddCause cmdAddCause = IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE;

		// 数据映射模式为数据属性ID（IEC61850_MAP_MODE_DAID）时，转换 dataMap 为 DAID
		IEC61850_DataAttributeID* daid = (IEC61850_DataAttributeID*)dataMap;
		IEC61850_PrintDataAttributeID(daid);

		// 数据映射模式为短地址（IEC61850_MAP_MODE_SADDR）或引用（IEC61850_MAP_MODE_REFERENCE）时，转换 dataMap 为 char*
		// printf("sAddr(or reference) is: [%s]\n", (char*)dataMap);	// 打印 sAddr 或 reference

		if (selectValue) {
			// 操作前选择请求为适用于 SBOes 控制对象的 SelectWithValue 请求
		} else {
			// 操作前选择请求为适用于 SBOns 控制对象的 Select 请求
		}

		return cmdAddCause;
	}
	\endcode
*/
typedef eCommandAddCause (*IEC61850_ControlSelectCallback)(void* userData, const void* dataMap, const IEC61850_DataAttributeData* selectValue, const IEC61850_CommandParameter* selectParameters);


/*!	\brief	操作前选择超时回调。
	\details
	用于控制服务。可用于得知操作前选择（SBOns / SBOes）控制对象发生选择超时（sboTimeout）。

	当客户端请求的 Select / SelectWithValue 操作前选择命令（例如调用了 `IEC61850_ControlSelect()` 接口）成功选择了控制对象时，服务端会对其启动 "选择超时" 的计时器，时限由操作前选择控制对象的 sboTimeout 数据属性决定，未配置则默认为 30 秒。若服务端在 sboTimeout 的时限内，没有接收到客户端对于该控制对象的 Operate / TimeActivatedOperate 操作命令，则已被选择的控制对象，将因择超时而返回未被选择（Unselected）状态。

	当操作前选择的控制对象发生选择超时时，服务端会调用该回调函数。
	回调的前提是，服务端的模型中，有为控制对象的 \"状态值\" 配置有与数据映射模式一致的数据属性映射。

	该回调函数应始终返回 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) ，不应返回其他 AddCause。

	\ingroup 	ServerCallback

	\param[in]	userData	自定义用户数据
	\param[in]	dataMap		数据属性映射。用于识别控制对象。<br>
							数据映射模式为数据属性ID（ #IEC61850_MAP_MODE_DAID ）时，对应的是控制对象 \"状态值\" 的 DAID，对应的数据类型是 `IEC61850_DataAttributeID*`；<br>
							数据映射模式为短地址（ #IEC61850_MAP_MODE_SADDR ）时，对应的是控制对象 \"状态值\" 的 sAddr，对应的数据类型是 `char*`；<br>
							数据映射模式为引用（ #IEC61850_MAP_MODE_REFERENCE ）时，对应的是控制对象的引用，对应的数据类型是 `char*`。
	\param[in]	selectValue	操作前选择命令所附带的选择控制值。<br>
							对于选择 SBOes 控制对象的 SelectWithValue 命令，该值有效；<br>
							对于选择 SBOns 控制对象的 Select 命令，该值为 NULL。

	\return		成功返回 #IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE ，失败返回适当的 附加的原因诊断 #eCommandAddCause

	\see IEC61850_SetUserData()

	<b>示例</b>
	\code
	eCommandAddCause SelectTimeoutCB(void* userData, const void* dataMap, const IEC61850_DataAttributeData* selectValue)
	{
		eCommandAddCause cmdAddCause = IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE;
		// dataMap 对应的控制对象发生操作前选择超时。已由 "准备就绪(Ready)" 状态变为 "未被选择(Unselected)" 状态

		// 数据映射模式为数据属性ID（IEC61850_MAP_MODE_DAID）时，转换 dataMap 为 DAID
		IEC61850_DataAttributeID* daid = (IEC61850_DataAttributeID*)dataMap;
		IEC61850_PrintDataAttributeID(daid);	// 打印 DAID

		// 数据映射模式为短地址（IEC61850_MAP_MODE_SADDR）或引用（IEC61850_MAP_MODE_REFERENCE）时，转换 dataMap 为 char*
		// printf("sAddr(or reference) is: [%s]\n", (char*)dataMap);	// 打印 sAddr 或 reference

		return cmdAddCause;
	}
	\endcode
*/
typedef eCommandAddCause (*IEC61850_ControlSelectTimeoutCallback)(void* userData, const void* dataMap, const IEC61850_DataAttributeData* selectValue);

/*!	\brief	运行测试回调。
	\details
	用于控制服务，可用于处理 Operate / TimeActivatedOperate 操作命令的运行测试（Operative Test）。

	当客户端请求了 Operate / TimeActivatedOperate 操作命令（例如调用了 `IEC61850_ControlOperate()` 接口）时，服务端会在操作时间（operTm）到达时调用该回调函数。对于 Operate 请求，操作时间的到达时刻为即刻；对于 TimeActivatedOperate 请求，操作时间的到达时刻为操作请求中指定的时刻。
	回调的前提是，服务端的模型中，有为控制对象的 \"状态值\" 配置有与数据映射模式一致的数据属性映射。

	其返回值指定为 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25)，代表运行测试通过（Operative Test OK），后续的控制流程将继续处理。
	若该回调函数中无任何处理，应返回 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25)；

	若返回值指定为 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) 以外的其他有效 AddCause 枚举值，则视为运行测试不通过（Operative Test Not OK），
	对应的 Operate / TimeActivatedOperate 操作命令将以指定的 AddCause 响应和动作。指定返回的 AddCause 应为适用于当下控制状态机的合理 AddCause。

	\ingroup 	ServerCallback

	\param[in]	userData				自定义用户数据
	\param[in]	dataMap					数据属性映射。用于识别控制对象。<br>
										数据映射模式为数据属性ID（ #IEC61850_MAP_MODE_DAID ）时，对应的是控制对象 \"状态值\" 的 DAID，对应的数据类型是 `IEC61850_DataAttributeID*`；<br>
										数据映射模式为短地址（ #IEC61850_MAP_MODE_SADDR ）时，对应的是控制对象 \"状态值\" 的 sAddr，对应的数据类型是 `char*`；<br>
										数据映射模式为引用（ #IEC61850_MAP_MODE_REFERENCE ）时，对应的是控制对象的引用，对应的数据类型是 `char*`。
	\param[in]	operativeTestParameters	控制参数信息

	\return		成功返回 #IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE ，失败返回适当的 附加的原因诊断 #eCommandAddCause

	\see IEC61850_SetUserData()

	<b>示例</b>
	\code
	eCommandAddCause OperativeTestCB(void* userData, const void* dataMap, const IEC61850_CommandParameter* operativeTestParameters)
	{
		eCommandAddCause cmdAddCause = IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE;

		// 数据映射模式为数据属性ID（IEC61850_MAP_MODE_DAID）时，转换 dataMap 为 DAID
		IEC61850_DataAttributeID* daid = (IEC61850_DataAttributeID*)dataMap;
		IEC61850_PrintDataAttributeID(daid);

		// 数据映射模式为短地址（IEC61850_MAP_MODE_SADDR）或引用（IEC61850_MAP_MODE_REFERENCE）时，转换 dataMap 为 char*
		// printf("sAddr(or reference) is: [%s]\n", (char*)dataMap);	// 打印 sAddr 或 reference

		if ((Boolean)operativeTestParameters->synchroCheck) {
			Boolean synchroCheckOK = TRUE;
			synchroCheckOK = FALSE;
			// 执行同期检查 SynchroCheck
			if (!synchroCheckOK) {
				printf("SynchroCheck NG\n");
				return IEC61850_COMMAND_ERROR_ADD_CAUSE_BLOCKED_BY_SYNCHROCHECK;
			}
		}

		if ((Boolean)operativeTestParameters->interlockCheck) {
			Boolean interlockCheckOK = TRUE;
			interlockCheckOK = FALSE;
			// 执行互锁检查 Interlock-Check
			if (!interlockCheckOK) {
				printf("Interlock-Check NG\n");
				return IEC61850_COMMAND_ERROR_ADD_CAUSE_BLOCKED_BY_INTERLOCKING;
			}
		}

		return cmdAddCause;
	}
	\endcode
*/
typedef eCommandAddCause (*IEC61850_ControlOperativeTestCallback)(void* userData, const void* dataMap, const IEC61850_CommandParameter* operativeTestParameters);


/*!	\brief	操作回调。
	\details
	用于控制服务，可用于得知客户端请求了操作 Operate 控制命令。

	当客户端请求了 Operate 操作命令（例如调用了 `IEC61850_ControlOperate()` 接口）时，服务端将在运行测试通过（Operative Test OK）之后，
	（即，运行测试回调函数 `IEC61850_ControlOperativeTestCallback` 返回 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) 之后），调用该回调函数。
	回调的前提是，服务端的模型中，有为控制对象的 \"状态值\" 配置有与数据映射模式一致的数据属性映射。

	服务端可基于该回调函数，触发和执行操作命令对应的实际控制动作，通常包括：

	- 识别客户端请求操作的控制对象以及控制值；
		（例如客户端请求操作开关控制器逻辑设备的 \"开关三相分合\" 状态 CSWI.Pos 为分或合）；
	- 对实际的物理设备执行客户端请求的操作动作；
		（例如服务端去实际控制物理开关设备的分或合）；
	- 等待并校验实际设备反馈的操作结果；
		（例如物理设备开关状态是否有成功变位到请求控制的分或合状态）；
	- 基于实际物理设备反馈的操作结果，更新控制对象对应的状态值。
		（例如依据物理开关设备受控后变化到的分或合状态，更新其对应开关控制器逻辑设备的 \"开关三相分合\" 状态值 CSWI.Pos.stVal 为 on 或 off）。

	其中，服务端对物理设备执行操作的动作，以及操作后对控制对象状态值的更新动作，都应该在该回调函数正常返回 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) 之后执行。

	指定返回值为 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25)，代表操作命令已被服务端接受。
	通常应固定返回 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25)，无论服务端实际是否执行了操作物理设备和更新状态值的动作；

	指定返回值为 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) 以外的其他有效 AddCause 枚举值，则视为操作执行异常，
	对应的 Operate / TimeActivatedOperate 操作命令将以指定的 AddCause 响应和动作。指定返回的 AddCause 应为适用于当下控制状态机的合理 AddCause。

	\ingroup 	ServerCallback

	\param[in]	userData			自定义用户数据
	\param[in]	dataMap				数据属性映射。用于识别控制对象。<br>
									数据映射模式为数据属性ID（ #IEC61850_MAP_MODE_DAID ）时，对应的是控制对象 \"状态值\" 的 DAID，对应的数据类型是 `IEC61850_DataAttributeID*`；<br>
									数据映射模式为短地址（ #IEC61850_MAP_MODE_SADDR ）时，对应的是控制对象 \"状态值\" 的 sAddr，对应的数据类型是 `char*`；<br>
									数据映射模式为引用（ #IEC61850_MAP_MODE_REFERENCE ）时，对应的是控制对象的引用，对应的数据类型是 `char*`。
	\param[in]	operateValue		操作命令所附带的控制值
	\param[in]	operateParameters	控制参数信息

	\return		成功返回 #IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE ，失败返回适当的 附加的原因诊断 #eCommandAddCause

	\see IEC61850_SetUserData()

	<b>示例</b>
	以下以客户端请求操作 CSWI.Pos 时的操作回调为例。<br>
	CSWI.Pos 的控制值是 BOOLEAN 类型；CSWI.Pos 的状态值（CSWI.Pos.stVal）是 Dbpos 类型。
	数据映射模式为数据属性ID（`IEC61850_MAP_MODE_DAID`）的操作回调函数例子：
	\code
	eCommandAddCause OperateCB(void* userData, const void* dataMap, const IEC61850_DataAttributeData* operateValue, const IEC61850_CommandParameter* operateParameters)
	{
		eCommandAddCause cmdAddCause = IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE;

		// 基于 dataMap 的值，来识别控制对象，
		// 进而确定由 operateValue 参数传入的 "控制值" 的数据类型，
		// 以及要实际控制的物理设备，和控制完成后需要更新的 "状态值" 的数据类型和数据属性映射信息。

		// 即，在服务端的模型（例如 server.cid）中，
		// 找到 dataMap 对应的数据属性（CSWI.Pos.stVal），
		// 找到后，可确定其所属的控制对象（CSWI.Pos），
		// 进而确定其 "控制值" 为 BOOLEAN 类型，"状态值"（CSWI.Pos.stVal）为 Dbpos 类型，
		// 记录 "状态值"（CSWI.Pos.stVal）的数据属性映射信息，用于更新状态值。

		// 转换 dataMap 参数为 DAID。
		// 该 DAID 是服务端模型中，为客户端请求操作的控制对象的 "状态值"（CSWI.Pos.stVal）绑定的 DAID。
		IEC61850_DataAttributeID* ctlID = (IEC61850_DataAttributeID*)dataMap;

		// 此处假设 dataMap 传入的 DAID 为 [0,1,2,3,4]
		// 执行相应的处理逻辑
		if ((ctlID->field1 == 0)
			&& (ctlID->field2 == 1)
			&& (ctlID->field3 == 2)
			&& (ctlID->field4 == 3)
			&& (ctlID->field5 == 4)) {
			// 控制对象 CSWI.Pos 的 "控制值" 是 BOOLEAN 类型，
			// 按 BOOLEAN 类型解析 operateValue 传入的控制值。
			Boolean ctlVal = *(Boolean*)operateValue->pvData;

			// return IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE;	// 令该回调函数返回 IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE
			// 并在该回调函数之外，执行对物理设备的操作，以及对状态值的更新处理。
			// 以下的示例代码仅用于理解控制流程。

			// 根据客户端请求的控制值，决定实际操作物理设备所使用的控制值。
			eDbPosValues physicalOperVal = DBPOS_OFF;	// 操作物理设备要使用的 Dbpos 操作值
			// 将客户端请求的 BOOLEAN 控制值，转换为操作物理设备要使用的 Dbpos 操作值。
			if (ctlVal == FALSE) {
				physicalOperVal = DBPOS_OFF;	// BOOLEAN 的控制值 FALSE，转换为 Dbpos 的状态值 off
			} else {
				physicalOperVal = DBPOS_ON;	// BOOLEAN 的控制值 TRUE，转换为 Dbpos 的状态值 on
			}

			// 此时，服务端应依据客户端请求的控制值，去实际 "操作" 物理设备。
			// （服务端对实际物理设备的操作控制，应由服务端自定义实现）
			// 同时，服务端应跟踪物理设备的操作情况，识别并保存物理设备反馈的实际操作结果。

			// 保存物理设备操作后的状态结果。
			// 服务端需要基于该结果，对控制对象的 "状态值" 做更新。
			eDbPosValues stVal = DBPOS_ON;	// 此处假设物理设备反馈的操作结果为 on

			// 分析服务端对物理设备的操作结果，根据情况，做控制对象 "状态值" 的更新处理。
			if (stVal == physicalOperVal	// 物理设备成功变位到客户端 "操作" 命令所请求的状态。（对于 CSWI.Pos.stVal 来说为 on 或 off）
				|| stVal == DBPOS_INTERMEDIATE || stVal == DBPOS_BAD) {	// 物理设备变位到了无效位置
				// 准备执行 "状态值" 的更新处理。
				// 可基于 DAID / sAddr / reference 的任意一种来做数据更新，
				// 此处以通过 DAID 来更新 "状态值" 为例。

				// 准备控制对象的 "状态值"（CSWI.Pos.stVal）的 DAID。（这里实际就是 dataMap 传入的 DAID）
				IEC61850_DataAttributeID daid = { 0, 1, 2, 3, 4 };

				// 准备控制对象 "状态值"（CSWI.Pos.stVal）的数据。
				IEC61850_DataAttributeData stValData = { 0 };
				stValData.type = IEC61850_DATATYPE_DBPOS;	// 指定数据类型。（CSWI.Pos.stVal 为 DBPos 类型）
				stValData.bitLength = IEC61850_DBPOS_BITSIZE;	// 指定数据大小（DBPos 数据的大小）
				stValData.pvData = &stVal;	// 指定数据属性的值为物理设备反馈的真实状态值

				// 调用数据更新接口，更新该控制对象的 "状态值"（CSWI.Pos.stVal）。
				IEC61850_ErrorCode eErrorCode = IEC61850_ERROR_NONE;
				IEC61850 myServer = GetMyServerClient();	// 获取 IEC61850 对象
				eErrorCode = IEC61850_Update(myServer, &daid, &stValData, 1);	// 通过 DAID 更新数据
				if (eErrorCode != IEC61850_ERROR_NONE) {
					// "状态值" 更新失败。
				} else {
					// "状态值" 更新成功。
				}
			} else {	// 物理设备未成功变位
				// 不更新 "状态值"。
				// 协议栈会在 operTimeout 的时间后，判定本次"操作"超时。
			}
		}
		return cmdAddCause;
	}
	\endcode

	数据映射模式为短地址（`IEC61850_MAP_MODE_SADDR`）的操作回调函数例子：
	\code
	eCommandAddCause OperateCB(void* userData, const void* dataMap, const IEC61850_DataAttributeData* operateValue, const IEC61850_CommandParameter* operateParameters)
	{
		eCommandAddCause cmdAddCause = IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE;

		// 转换 dataMap 为短地址。即，"状态值"（CSWI.Pos.stVal）的 sAddr
		const char* sAddr = (const char*)dataMap;

		// 基于短地址识别控制对象，并进入对应的处理逻辑。
		// 此处假设 dataMap 传入的短地址为 "stValsAddrExample"
		if (strcmp(sAddr, "stValsAddrExample") == 0) {
			// 依据识别到的控制对象，来判断由 operateValue 参数传入的 "控制值" 的数据类型，并解析传入的 "控制值"。
			Boolean ctlVal = *(Boolean*)operateValue->pvData;	// 双点位置（Dbpos）的 "控制值" 是 BOOLEAN 类型。

			// return IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE;	// 令该回调函数返回 IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE
			// 并在该回调函数之外，执行对物理设备的操作，以及对状态值的更新处理。
			// 以下的示例代码仅用于理解控制流程。

			// 依据 "控制值" 去操作实际的物理设备，并保存物理设备操作后的状态结果。
			eDbPosValues stVal = DBPOS_ON;	// 应根据物理设备反馈的状态赋值

			// 准备执行 "状态值" 的更新处理。
			// 可基于 DAID / sAddr / reference 的任意一种来做数据更新，
			// 此处以通过 sAddr 来更新 "状态值" 为例。

			// 准备更新用的 "状态值"（CSWI.Pos.stVal） 的短地址。（这里实际就是 dataMap 传入的 sAddr）
			char* sAddrList[1] = { "stValsAddrExample" };	// 此处假设 "状态值" 的短地址为 "stValsAddrExample"

			// 准备更新用的 "状态值"（CSWI.Pos.stVal）的数据。
			IEC61850_DataAttributeData stValData = { 0 };
			stValData.type = IEC61850_DATATYPE_DBPOS;
			stValData.bitLength = IEC61850_DBPOS_BITSIZE;
			stValData.pvData = &stVal;

			// 调用数据更新接口，更新该控制对象在服务端中的 "状态值"（CSWI.Pos.stVal）。
			IEC61850_ErrorCode eErrorCode = IEC61850_ERROR_NONE;
			IEC61850 myServer = GetMyServerClient();
			eErrorCode = IEC61850_UpdateWithShortAddr(myServer, &sAddrList, &stValData, 1);	// 通过 sAddr 更新数据
			if (eErrorCode != IEC61850_ERROR_NONE) {
				// "状态值" 更新失败。
			} else {
				// "状态值" 更新成功。
			}
		}
		return cmdAddCause;
	}
	\endcode

	数据映射模式为引用（ #IEC61850_MAP_MODE_REFERENCE ）的操作回调函数例子：
	\code
	eCommandAddCause OperateCB(void* userData, const void* dataMap, const IEC61850_DataAttributeData* operateValue, const IEC61850_CommandParameter* operateParameters)
	{
		eCommandAddCause cmdAddCause = IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE;

		// 转换 dataMap 为引用
		const char* reference = (const char*)dataMap;

		// 通过 dataMap 传入的引用，为请求控制的数据对象的引用。
		// 需要注意的是，引用路径仅到控制对象的数据对象层级，
		// 即，引用的值是 "LDName/LNName.DOName"，而不是 "LDName/LNName.DOName.Oper.ctlVal"

		// 基于引用识别控制对象
		if (strcmp(reference, "LDName/CSWI0.Pos") == 0) {
			// 依据识别到的控制对象，来判断由 operateValue 参数传入的 "控制值" 的数据类型，并解析传入的 "控制值"。
			Boolean ctlVal = *(Boolean*)operateValue->pvData;	// 双点位置（Dbpos）的 "控制值" 是 BOOLEAN 类型。

			// return IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE;	// 令该回调函数返回 IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE
			// 并在该回调函数之外，执行对物理设备的操作，以及对状态值的更新处理。
			// 以下的示例代码仅用于理解控制流程。

			// 依据 "控制值" 去操作实际的物理设备，并保存物理设备操作后的状态结果。
			eDbPosValues stVal = DBPOS_ON;	// 应根据物理设备反馈的状态赋值

			// 准备执行 "状态值" 的更新处理。
			// 可基于 DAID / sAddr / reference 的任意一种来做数据更新，
			// 此处以通过 引用 来更新 "状态值" 为例。

			// 准备更新用的 "状态值"（CSWI.Pos.stVal） 的引用。
			char* stValRef = "ServerIEDExample/CSWI0.Pos.stVal";	// 引用值仅为示例

			// 准备更新用的 "状态值"（CSWI.Pos.stVal）的数据。
			IEC61850_DataAttributeData stValData = { 0 };
			stValData.type = IEC61850_DATATYPE_DBPOS;
			stValData.bitLength = IEC61850_DBPOS_BITSIZE;
			stValData.pvData = &stVal;

			// 调用数据更新接口，更新该控制对象在服务端中的 "状态值"（CSWI.Pos.stVal）。
			IEC61850 myServer = GetMyServerClient();
			IEC61850_ErrorCode eErrorCode = IEC61850_UpdateWithReference(myServer, stValRef, &stValData);	// 通过引用更新数据
			if (eErrorCode != IEC61850_ERROR_NONE) {
				// "状态值" 更新失败。
			} else {
				// "状态值" 更新成功。
			}
		}
		return cmdAddCause;
	}
	\endcode
*/
typedef eCommandAddCause (*IEC61850_ControlOperateCallback)(void* userData, const void* dataMap, const IEC61850_DataAttributeData* operateValue, const IEC61850_CommandParameter* operateParameters);

/*!	\brief	取消回调。
	\details
	用于控制服务。该回调函数会在以下场景下被服务端调用：

	- 当客户端请求了 Cancel 取消命令（例如调用了 `IEC61850_ControlCancel()` 接口），服务端会在接受 Cancel 命令的执行时调用该回调函数。
	- 当客户端对已经选择成功了的操作前选择（SBOns 或 SBOes）控制对象，请求执行 Opeate / TimeActivatedOperate 命令时，
		若因运行测试未通过（Operative Test Not OK）等异常原因，被服务端撤销了选择状态并终止执行控制操作时，服务端也会调用该回调函数。
		此种情况下，同时会在 `cancelParameters` 参数中标记 "回调由内部堆栈条件触发标记（bStackGenerated）" 的成员值为 TRUE，用于告知客户端控制对象的选择状态被取消。

	回调的前提是，服务端的模型中，有为控制对象的 \"状态值\" 配置有与数据映射模式一致的数据属性映射。

	该回调函数通常仅应返回 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) ，不应返回其他 AddCause。
	特殊的，令该回调函数返回 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NOT_SUPPORTED` (1)，可以拒绝对控制对象执行的 Cancel 命令。

	\ingroup 	ServerCallback

	\param[in]	userData			自定义用户数据
	\param[in]	dataMap				数据属性映射。用于识别控制对象。<br>
									数据映射模式为数据属性ID（ #IEC61850_MAP_MODE_DAID ）时，对应的是控制对象 \"状态值\" 的 DAID，对应的数据类型是 `IEC61850_DataAttributeID*`；<br>
									数据映射模式为短地址（ #IEC61850_MAP_MODE_SADDR ）时，对应的是控制对象 \"状态值\" 的 sAddr，对应的数据类型是 `char*`；<br>
									数据映射模式为引用（ #IEC61850_MAP_MODE_REFERENCE ）时，对应的是控制对象的引用，对应的数据类型是 `char*`。
	\param[in]	cancelParameters	控制参数信息

	\return		成功返回 #IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE ，失败返回适当的 附加的原因诊断 #eCommandAddCause

	\see IEC61850_SetUserData()

	<b>示例</b>
	\code
	eCommandAddCause CancelCB(void* userData, const void* dataMap, const IEC61850_CommandParameter* cancelParameters)
	{
		eCommandAddCause cmdAddCause = IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE;
		// 客户端请求取消对 dataMap 对应控制对象的控制请求

		// 数据映射模式为数据属性ID（IEC61850_MAP_MODE_DAID）时，转换 dataMap 为 DAID
		IEC61850_DataAttributeID* daid = (IEC61850_DataAttributeID*)dataMap;
		IEC61850_PrintDataAttributeID(daid);	// 打印 DAID

		// 数据映射模式为短地址（IEC61850_MAP_MODE_SADDR）或引用（IEC61850_MAP_MODE_REFERENCE）时，转换 dataMap 为 char*
		// printf("sAddr(or reference) is: [%s]\n", (char*)dataMap);	// 打印 sAddr 或 reference

		return cmdAddCause;
	}
	\endcode
*/
typedef eCommandAddCause (*IEC61850_ControlCancelCallback)(void* userData, const void* dataMap, const IEC61850_CommandParameter* cancelParameters);


/*!	\brief	命令终止回调。
	\details
	用于控制服务。客户端可基于该回调函数，得知服务端对客户端请求的操作命令的最终执行结果。

	当客户端接收到服务端上送的 CommandTermination 请求时，客户端会调用该回调函数。
	既会由 CommandTermination_req+ 触发，也会由 CommandTermination_req- 触发。

	只有客户端对增强安全的（DOes 或 SBOes）控制对象执行 Operate 操作命令时，服务端才会在控制流程的最后上送 CommandTermination 请求给客户端。
	对于控制常规安全的（DOns 或 SBOns）控制对象的场景，不涉及 CommandTermination 请求的上送，不会触发该回调函数的执行。

	\ingroup 	ClientCallback

	\param[in]	userData		自定义用户数据
	\param[in]	dataMap			数据属性映射。用于识别控制对象。<br>
								数据映射模式为数据属性ID（ #IEC61850_MAP_MODE_DAID ）时，对应的是控制对象 \"状态值\" 的 DAID，对应的数据类型是 `IEC61850_DataAttributeID*`；<br>
								数据映射模式为短地址（ #IEC61850_MAP_MODE_SADDR ）时，对应的是控制对象 \"状态值\" 的 sAddr，对应的数据类型是 `char*`；<br>
								数据映射模式为引用（ #IEC61850_MAP_MODE_REFERENCE ）时，对应的是控制对象的引用，对应的数据类型是 `char*`。
	\param[in]	controlResult	控制结果信息

	\return		该回调函数应始终返回 `IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE` (25) ，不应返回其他 AddCause。

	\see IEC61850_SetUserData()
*/
typedef eCommandAddCause (*IEC61850_ControlCommandTerminationCallback)(void* userData, const void* dataMap, const ControlResult* controlResult);

/*!	\brief	连接状态回调。
	\details
	用于得知客户端与服务端连接状态的变化。
	当客户端与服务端的连接状态发生变化时（例如关联丢失，或者重新关联时），该回调函数会在客户端被调用。

	\ingroup 	ClientCallback

	\param[in]	userData				自定义用户数据
	\param[in]	connectedServersArray	服务端的连接状态列表

	\see IEC61850_SetUserData() , IEC61850_GetConnectionsList()

	<b>示例</b>
	\code
	void ConnectionStatusCB(void* userData, struct IEC61850_ServerStatusArray connectedServersArray)
	{
		// 客户端与服务端的连接状态发生变化
	}
	\endcode
*/
typedef void (*IEC61850_ConnectionStatusCallback)(void* userData, IEC61850_ServerStatusArray connectedServersArray);

/*!	\brief	时间戳回调。
	\details
	用于替代 YX-PIS 协议栈内置的方法，以自定义的方法计算和提供当前时间。

	YX-PIS 协议栈中，服务端和客户端会通过调用 `IEC61850_GetTime()` 接口来获取当前时间。
	协议栈已经对 `IEC61850_GetTime()` 接口内计算和获取当前时间的方法，做了基本的多平台环境适配，通常情况下无需定义和使用该回调函数。

	若该回调函数在 IEC61850 对象的属性参数中未被指定，该回调函数不会被调用。`IEC61850_GetTime()` 接口将按内置的默认方法获取和返回当前时间；
	若该回调函数在 IEC61850 对象的属性参数中有被指定，则该回调函数将在调用 `IEC61850_GetTime()` 接口时被调用。用户需要在该回调函数内实现对当前时间的获取和计算，并通过 `CurrentTime` 参数传出，随后 `IEC61850_GetTime()` 接口将返回由该回调函数提供的时间。

	\ingroup 	ServerandClientCallback

	\param[in]	userData	自定义用户数据
	\param[in]	timestamp	以自定义的方法获取和计算的当前时间

	\return		无返回值

	\see	IEC61850_SetUserData()

	<b>示例</b>
	\code
	void TimeStampCB(void* userData, IEC61850_TimeStamp* timestamp)
	{
		// 按自定义的方法获取当前时间，并赋值给 timestamp 参数
		timestamp->seconds = 1674448496;
	}
	\endcode
*/
typedef void (*IEC61850_TimeStampCallback)(void* userData, IEC61850_TimeStamp* timestamp);

/*!	\brief	文件回调。
	\details
	用于文件服务。可用于得知客户端请求的文件读写服务类别，以及请求的文件信息。
	该回调函数会在客户端请求了文件相关的 ACSI 时，在服务端被调用。

	\ingroup 	ServerCallback

	\param[in]	userData		自定义用户数据
	\param[in]	fileCallType	请求的文件调用类别。用于指示客户端请求的文件服务。
	\param[in]	fileAttributes	文件属性信息

	\return	文件请求响应码 #IEC61850_FileResponseCode

	\see IEC61850_SetUserData()

	<b>示例</b>
	\code
	enum IEC61850_FileResponseCode FileCB(void* userData, enum IEC61850_FileCallType fileCallType, struct tFileAttr* fileAttributes)
	{
		enum IEC61850_FileResponseCode responseCode = IEC61850_FILE_RESPONSE_ACCEPT;
		U32 fileIndex = 0;

		switch (fileCallType)
		{
		case IEC61850_FILE_CALL_READ:
			// printf("读文件: %s\n", fileAttributes->primaryFile.fileName);
			break;
		case IEC61850_FILE_CALL_GET_ATTRIBUTES:
			// printf("获取文件(或目录)'%s'的属性\n", fileAttributes->primaryFile.fileName);
			if (strcmp(fileAttributes->primaryFile.fileName, "MySecretDirectory") == 0) {
				responseCode = IEC61850_FILE_RESPONSE_ACCESS_DENIED;
			}
			break;
		case IEC61850_FILE_CALL_DELETE:
			// 设置返回值 responseCode 为 IEC61850_FILE_RESPONSE_ACCEPT 将允许删除文件
			// 设置返回值 responseCode 为 IEC61850_FILE_RESPONSE_ACCESS_DENIED 将禁止删除文件
			if (responseCode == IEC61850_FILE_RESPONSE_ACCESS_DENIED) {
				// printf("不允许删除文件'%s'\n", fileAttributes->primaryFile.fileName);
			} else if (responseCode == IEC61850_FILE_RESPONSE_ACCEPT) {
				// printf("允许删除文件'%s'\n", fileAttributes->primaryFile.fileName);
			} else {
				// printf("要删除的文件'%s'不存在\n", fileAttributes->primaryFile.fileName);
			}

			break;
		case IEC61850_FILE_CALL_SET_FILE:
			// printf("写文件。服务端下载的文件为'%s', 客户端上传的文件为'%s'\n", fileAttributes->primaryFile.fileName, fileAttributes->directoryEntries[0].fileName);
			break;
		default:
			// printf("无效的文件服务调用类别：%d\n", fileCallType);
			break;
		}
		return responseCode;
	}
	\endcode
*/
typedef IEC61850_FileResponseCode (*IEC61850_FileCallback)(void* userData, IEC61850_FileCallType fileCallType, tFileAttr* fileAttributes);

/*!	\brief	定值组操作回调。
	\details
	用于定值服务。可用于得知客户端请求了选择激活定值组、选择编辑定值组动作。
	该回调函数会在客户端请求了定值组相关操作时，在服务端被调用。

	\ingroup	ServerCallback

	\param[in]	userData	自定义用户数据
	\param[in]	sgOper		请求的定值组操作
	\param[in]	sgParam		定值组回调参数，不同的sgOper传递参数不同

	\return		返回 #SERVICE_ERROR_NO_ERROR ，将允许执行当次的定值组操作；返回 #SERVICE_ERROR_FAILED_DUE_TO_SERVER_CONSTRAIANT ，将禁止执行当次的定值组操作

	\see IEC61850_SetUserData()
*/
typedef eServiceError(*IEC61850_SettingGroupCallback)(void* userData, IEC61850_SettingGroup_Operation sgOper, void* sgParam);

/*!	\brief	文件路径转换回调函数。
	\details
	用于文件服务 #SC_GetFile  #SC_SetFile  #SC_DeleteFile  #SC_GetFileAttributeValues #SC_GetFileDirectory 。
	该回调函数会在服务端被调用。

	\ingroup 	ServerCallback

	\param[in]	serviceCode		服务代码 enum ServiceCode 128-132   
								#SC_GetFile  #SC_SetFile  #SC_DeleteFile  #SC_GetFileAttributeValues #SC_GetFileDirectory 。
	\param[in]	path			文件路径
	\param[out] out				转换后的路径
	\param[in]	length			路径长度

	\return		void
*/
typedef Boolean (*IEC61850_FilePathResolveCallback)(int serviceCode, const char* path, char* out, int length);

/*!	\brief	(保留内容，暂不支持。**禁止使用**)

	\ingroup 	ServerAndClientCallback

	\param[in]	userData	自定义用户数据
	\param[in]	cbid		数据属性id
	\param[in]	newValues	数值指针
	\param[in]	length		数值长度

	\return		none

	\see IEC61850_SetUserData()
*/
typedef void (*IEC61850_ReportUpdateCallback)(void* userData, const void* cbid, const void* newValues, const unsigned int length);

/*!	\brief	用于报告FCDA更新回调。
	\details
	该回调函数会在客户端接收到报告时触发。触发机制与 #IEC61850_FCDAUpdateCallback 相同。
	该回调函数以FCDA为单位触发。
	仅适用于报告服务。

	\ingroup 	ClientCallback

	\param[in]	userData	自定义用户数据
	\param[in]	dataMap		更新的数据值的数据映射
	\param[in]	newValue	以FCDA为单位的数据值
	\param[in]	dataNum		数据数量

	\return		返回 #SERVICE_ERROR_NO_ERROR ，将允许执行当次的定值组操作；返回 #SERVICE_ERROR_FAILED_DUE_TO_SERVER_CONSTRAIANT ，将禁止执行当次的定值组操作
*/
typedef void (*IEC61850_FCDAUpdateCallback)(void* userData, const void* dataMap, const struct IEC61850_DataAttributeData* newValue, unsigned int dataNum);


/*!	\brief	IEC61850报告数据条目结构体 */
typedef struct IEC61850_ReportDataEntry
{
	U16 id;								/*!< 数据条目标识符 */
	char reference[130];				/*!< 数据引用路径 */
	char fc[3];							/*!< 功能约束码(如"MX"表示测量值) */
	IEC61850_DataAttributeData data;	/*!< 数据属性值 */
	U8 reasonCode;						/*!< 数据变化原因码 */
} IEC61850_ReportDataEntry;

/*!	\brief	日期时间结构体 */
typedef struct IEC61850_TimeOfDay
{
	U32 time;    /*!< 时间戳(毫秒) */
	U16 date;    /*!< 日期(Julian日期格式) */
} IEC61850_TimeOfDay;

/*!	\brief	客户端报告数据结构体 */
typedef struct IEC61850_ClientReportData
{
	char rptID[130];					/*!< 报告控制块标识符 */
	U16 optFlds;						/*!< 选项字段位掩码 */
	U32 seqNum;							/*!< 报告序列号 */
	IEC61850_TimeOfDay timeOfEntry;		/*!< 报告生成时间 */
	char dataset[130];					/*!< 关联的数据集名称 */
	Boolean bufOvfl;					/*!< 缓冲区溢出标志 */
	U8 entryID[8];						/*!< 条目唯一标识 */
	U32 confRev;						/*!< 配置版本号 */
	U16 subSqNum;						/*!< 子序列号 */
	Boolean moreSegmentsFollow;			/*!< 多段传输标志 */
	U8* inclusion;						/*!< 包含位图(需调用者释放) */
	U32 numOfInclusion;					/*!< 包含位图长度 */
	IEC61850_ReportDataEntry* entries;	/*!< 数据条目数组(需调用者释放) */
	U32 numOfEntry;						/*!< 数据条目数量 */
} IEC61850_ClientReportData;

/*!	\brief	报告更新回调函数类型 */
typedef void (*IEC61850_ReportUpdateDirectCallback)(void* userData, IEC61850_ClientReportData* data);

/*!	\brief	GOOSE监控数据结构体 */
typedef struct IEC61850_GooseMonitorData {
	U16 appId;					/*!< 应用标识符 */
	char gocbRef[130];			/*!< GOOSE控制块引用 */
	char datasetName[130];		/*!< 关联的数据集名称 */
	char gooseId[130];			/*!< GOOSE标识符 */
	U32 timeTillExpiration;		/*!< 过期剩余时间(毫秒) */
	U32 sequenceNumber;			/*!< 序列号 */
	U32 configurationRevision;	/*!< 配置版本号 */
	Boolean testMode;			/*!< 测试模式标志 */
	Boolean needsCommissioning;	/*!< 需要调试标志 */
	U32 datasetSize;			/*!< 数据集大小 */
} IEC61850_GooseMonitorData;

/*!	\brief	GOOSE监控回调函数类型 */
typedef void (*IEC61850_GooseMonitorCallback)(void* userData, IEC61850_GooseMonitorData* data);

/*!	\brief	文件服务属性。（CMS 版本未使用） */
typedef struct FileServiceOption
{
	Boolean specifyFileServices;	/*!< 使能标记。<br>该成员值为 TRUE 时，以下的其他成员值将被应用；<br>该成员值为 FALSE 时，将无视该结构体的所有成员值。 */
	Boolean enableGetFile;			/*!< 允许读文件标志<br>TRUE：允许；<br>FALSE：禁止。 */
	Boolean enableSetFile;			/*!< 允许写文件标志<br>TRUE：允许；<br>FALSE：禁止。 */
	Boolean enablefileDelete;		/*!< 允许删除文件标志<br>TRUE：允许；<br>FALSE：禁止。 */
	Boolean enableFileDirectory;	/*!< 允许读文件目录标志<br>TRUE：允许；<br>FALSE：禁止。 */
	Boolean enableObtainFile;		/*!< 允许文件操作标志。<br>TRUE：允许；<br>FALSE：禁止。 */
} FileServiceOption;

/*!	\brief	服务端/客户端的属性参数。
	\details
	用于为 `IEC61850_Create()` 接口创建的 IEC61850 对象配置详细属性。<br>
	具体请参照每个成员的说明。<br>
	以下是对于用户主要需要关注和设置的数据成员的说明：<br>
	- clientServerFlag：<br>
		用于标识 IEC61850 对象角色(服务端/客户端)。必须被设为 #IEC61850_SERVER 或 #IEC61850_CLIENT 。

	- Ed1_Ed2_Flag：<br>
		用于表示 IEC61850 对象版本。其值为 enum #IEC61850_Ed1_Ed2_Flag 的枚举类型。<br>
		通常指定为 #IEC61850_Edition2 。<br>
		同一环境内有通信交互关系的服务端、客户端对象，应使用相同的版本。

	- options：<br>
		用于设置 IEC61850 对象的可选参数。可以指定为 enum #IEC61850_OptionFlag 枚举值中的一个或多个选项。<br>
		指定多个选项时，选项之间需要为 “或(`|`)” 运算的关系。

	- maxServerAssociations：<br>
		服务端的最大关联数量。不设置时，默认值为 16。

	- maxClientAssociations：<br>
		客户端的最大关联数量。不设置时，默认值为 16。

	- dataMapMode：<br>
		数据映射模式。代表协议栈检索和映射模型中的数据属性所使用的资源。<br>
		该属性的值，将决定回调函数的数据属性映射参数 `dataMap` 所传入的数据类型。（无视数据映射模式的回调除外）
		- 指定为 #IEC61850_MAP_MODE_DAID ，代表属数据以数据属性ID（DAID）的方式映射，
			回调函数中的 `dataMap` 参数将为 `IEC61850_DataAttributeID*` 类型的数据属性ID；
		- 指定为 #IEC61850_MAP_MODE_SADDR ，代表属数据以短地址（sAddr）的方式映射，
			回调函数中的 `dataMap` 参数将为 `char*` 类型的短地址；
		- 指定为 #IEC61850_MAP_MODE_REFERENCE ，代表属数据以引用（Reference）的方式映射，
			回调函数中的 `dataMap` 参数将为 `char*` 类型的引用。

		不指定时，数据映射模式默认为 #IEC61850_MAP_MODE_DAID ；<br>
		不支持同时设置多种映射模式。

	- 回调函数地址：<br>
		根据回调函数属性，用户通常需要为服务端/客户端指定以下回调函数，其他回调函数可以不设置或按需设置。
		- 客户端
			- fnUpdateCallback
		- 服务端
			- fnOperateCallback
			- fnFileCallback
		- 服务端订阅端
			- fnUpdateCallback
			- fnQuestionableCallback

	\attention
	强烈建议在定义该结构体变量的当下，就对其做整体置 0 的初始化，（例如： `struct IEC61850_Parameters para = { 0 };`） ，以确保未使用到的数据成员为 0 值。<br>
	对于无需关注，或者未做设置的参数，请务必将其设置为 0 值（0 或 NULL），以避免内存中的随机值影响协议栈的正常运作。

	\see IEC61850_Create()
*/
typedef struct IEC61850_Parameters
{
	IEC61850_ClientServerFlag					clientServerFlag;			/*!< 角色标志（服务端/客户端） */
	IEC61850_Ed1_Ed2_Flag						Ed1_Ed2_Flag;				/*!< 版本标志（版本一/版本二） */
	IEC61850_LoadSGDataFlag						loadUpdatedSGDataFlag;		/*!< 定值数据初始加载方案。 \see #IEC61850_LoadSGDataFlag */
	U16											cmsTimeout;					/*!< 通信超时时间。单位为毫秒。<br>未设置或设置为 0，则默认为 400 毫秒；若设置，请设置为 10 毫秒的倍数 */
	char**										authArray;					/*!< 认证信息。是一个数组，包含客户端连接到服务器时要发送的密码。指定为 NULL 代表不需要身份验证；若指定，则数据元素顺序应与 CID 文件中的服务端 IED 顺序相同 */
	U32											authArraySize;				/*!< 认证信息元素数量 */
	U8											serverRootSubDirDepth;		/*!< 服务端根文件夹目录深度 */
	S16											defaultResvTms;				/*!< 缓存报告控制块的默认保留时间(ResvTms)。单位为秒。<br>是被占用的 BRCB 实例未被客户端设置 ResvTms 时，BRCB 实例默认的 ResvTms 值。<br>不设置或设置为 0，则默认为 60 秒 */
	U32											settingGroupResvTimeout;	/*!< 定值组编辑的保留时间。单位为毫秒。<br>不设置或设置为 0，则默认为 30000 毫秒 */
#ifndef __PARADIGM__
	unsigned int 								options;					/*!< IEC61850 对象的可选参数。 \see #IEC61850_OptionFlag */
	int											cmdTermTimeout;				/*!< 控制服务的命令终止判定时间。<br>是协议栈在接收到有效的操作命令后，在评估命令终止之前等待的时间。单位为毫秒。<br>不设置或设置为 0，则默认为 10000 毫秒 */
	unsigned int								maxServerAssociations;		/*!< 服务端的最大关联数量。不设置或设置为 0，则默认为 16 */
	unsigned int								maxClientAssociations;		/*!< 客户端的最大关联数量。不设置或设置为 0，则默认为 16 */
#else
	unsigned long int							options;					/*!< 选项标志，用于设置客户端/服务器全局选项，有关值，请参见 #IEC61850_OptionFlag */
	unsigned long int							cmdTermTimeout;				/*!< 控制服务的命令终止判定时间。单位为毫秒。<br>是协议栈在接收到有效的操作命令后，在评估命令终止之前等待的时间。<br>不设置或设置为 0，则默认为 10000 毫秒。 */
	unsigned long int							maxServerAssociations;		/*!< 服务端的最大关联数量。不设置或设置为 0，则默认为 16 */
	unsigned long int							maxClientAssociations;		/*!< 客户端的最大关联数量。不设置或设置为 0，则默认为 16 */
#endif
	IEC61850_DataMapMode						dataMapMode;				/*!< 数据映射模式 此处配置决定回调函数传递的参数 */
	FileServiceOption							supportedFileService;		/*!< 受支持的文件服务（CMS版本不使用该成员） */
	const char*									configPath;					/*!< 客户端或服务端的配置文件路径 */
	const char*									fileHandlingRootDir;		/*!< 文件处理的根目录，必须是一个以nul结尾的字符串，并且必须少于128个字符 */

	IEC61850_UpdateCallback						fnUpdateCallback;			/*!< 更新回调函数地址 */
	IEC61850_DataPointQuestionableCallback		fnQuestionableCallback;		/*!< 数据点品质可疑回调函数地址 */

	IEC61850_ControlSelectTestCallback			fnSelectTestCallback;		/*!< 选择测试回调函数地址 */
	IEC61850_ControlSelectCallback				fnSelectCallback;			/*!< 选择回调函数地址 */
	IEC61850_ControlSelectTimeoutCallback		fnSelectTimeoutCallback;	/*!< 选择超时回调函数地址 */
	IEC61850_ControlOperativeTestCallback		fnOprTestCallback;			/*!< 运行测试回调函数地址 */
	IEC61850_ControlOperateCallback				fnOperateCallback;			/*!< 操作回调函数地址 */
	IEC61850_ControlCancelCallback				fnCancelCallback;			/*!< 取消回调函数地址 */
	IEC61850_ControlCommandTerminationCallback	fnCmdTermCallback;			/*!< 命令终止回调函数地址 */

	IEC61850_ConnectionStatusCallback			fnConnectionStatusCallback; /*!< 连接状态回调函数地址 */
	IEC61850_TimeStampCallback					fnTimestampCallback;		/*!< 时间戳回调函数地址 */
	IEC61850_SettingGroupCallback				fnSettingGroupCallback;		/*!< 定值组操作回调函数地址 */
	IEC61850_FileCallback						fnFileCallback;				/*!< 文件回调函数地址 */
	IEC61850_FilePathResolveCallback			fnFilePathResolveCallback;	/*!< 文件路径转换回调函数地址 */

	IEC61850_ReportUpdateCallback				fnReportUpdateCallback;		/*!< **禁止使用** */
	IEC61850_FCDAUpdateCallback					fnFCDAUpdateCallback;		/*!< 以FCDA为单位的更新回调函数地址 */
	IEC61850_ReportUpdateDirectCallback			fnReportUpdateDirectCallback;	/*!< **禁止使用** */
	IEC61850_GooseMonitorCallback				fnGooseMonitorCallback;		/*!< **禁止使用** */

	IEC61850_WriteCallback						fnWriteCallback;			/*!< 写回调函数地址 */
} IEC61850_Parameters;

/*!	\brief	数据源标识结构体 */
typedef struct tOriginator
{
	U8 orCat;        /*!< 数据源类别(1字节) */
	U8 orIdent[64];  /*!< 数据源标识符(64字节) */
} tOriginator;

/*!	\brief	控制参数。
用于客户端发送的控制命令。 */
typedef struct IEC61850_ControlParameters
{
	U32		timeout;			/*!< 未使用的无意义参数。**禁止使用** */
	Boolean	synchroCheck;		/*!< 同期检查标志。<br>0 值代表指定控制请求中的同期检查（SynchroCheck）标志为 FALSE；<br>非 0 值代表指定控制请求中的同期检查（SynchroCheck）标志为 TRUE。 */
	Boolean	interlockCheck;		/*!< 互锁检查标志。<br>0 值代表指定控制请求中的同期检查（Interlock-Check）标志为 FALSE；<br>非 0 值代表指定控制请求中的同期检查（Interlock-Check）标志为 TRUE。 */
	Boolean	testFlag;			/*!< 测试标志。<br>0 值代表指定控制请求中的测试（Test）标志为 FALSE；<br>非 0 值代表指定控制请求中的测试（Test）标志为 TRUE。 */
	IEC61850_TimeStamp* operTm; /*< struct IEC61850_TimeStamp\* | 激活控制的时间（operTm），即，"操作" 动作的执行时刻。<br>仅在 "时间激活" 的控制流程中使用。<br>对带有 "operTm" 数据属性的控制对象请求的 "带值的操作前选择(SelectWithValue)" 命令、"时间激活的操作(TimeActivatedOperate)" 命令，以及"取消(Cancel)"控制命令，会按照 "时间激活" 的控制流程执行，需要在响应的控制请求中，为该成员指定有效的时间值，不能指定为 NULL。并且，属于同一控制序列的控制命令所附带的激活时间应该相同；<br>对不带有 "operTm" 数据属性的控制对象请求控制命令时，会按照该成员值应始终指定为 NULL。 */
	tOriginator* originator;	/*!< 控制发起者  */
	U8      ctlNum;				/*!< 控制请求编号 */
	eCommandAddCause addCause;	/*!< 控制失败时返回的附加原因码 */
} IEC61850_ControlParameters;

/*!	\brief	日期时间。包含年、月、日、时、分、秒、微秒。 */
typedef struct IEC61850_DateTime {
	U32		tm_uSec;	/*!< 微秒。取值应为 0~999999 */
	U8		tm_sec;		/*!< 秒。取值应为 0~59 */
	U8		tm_min;		/*!< 分。取值应为 0~59 */
	U8		tm_hour;	/*!< 时。取值应为 0~23 */
	U8		tm_mday;	/*!< 日。取值应为 1~31 */
	U8		month;		/*!< 月。取值应为 1~12 */
	U16		year;		/*!< 年。取值应大于等于 1970 */
} IEC61850_DateTime;

/*!	\brief	连接信息 */
typedef struct RemoteConnection
{
	int		AAIndex;			/*!< 应用关联的索引号。<br>如果是客户端请求获取服务端的连接状态，则该值为客户端模型文件中引用的所有 ServerIED 在文件中的定义顺序的索引，值从 0 开始，最先引用的首个 ServerIED 的索引值为 0 ，若包含多个 ServerIED，则后续其他 ServerIED 的索引值按顺序依次递增 1；<br>如果是服务端请求获取客户端的连接状态，则该值为与当前服务端处于连接中状态的所有客户端的索引编号。值从 1 开始，多个连接的客户端的索引值依次递增 1，顺序为客户端与服务端关联的先后顺序。 */
	char*	iedName;			/*!< 客户端关联的服务端 IED 名称。<br>如果是客户端请求获取服务端的连接状态，则该值为客户端模型文件中引用的 ServerIED 的 IED 名称；<br>如果是服务端请求获取客户端的连接状态，则该值为 NULL。 */
	char*	IPAddress;			/*!< IP 地址。<br>如果是客户端请求获取服务端的连接状态，则该值为服务端 IED 对应接入点的 IP 地址；<br>如果是服务端请求获取客户端的连接状态，则该值为与当前服务端关联的客户端对应的 IP 地址。 */
	Boolean	bConnectionState;	/*!< 连接状态。<br>TRUE：连接中；<br>FALSE：连接断开。 */
} RemoteConnection;

/*!	\brief	连接列表 */
typedef struct ConnectionList
{
	U16					length;	/*!< 连接数 */
	RemoteConnection*	connections;				/*!< 连接信息 */
} ConnectionList;

/*!	\brief	GOOSEControlBlocks structure to get GOOSE CB information */
typedef struct GOOSEControlBlocks
{
	Boolean Enabled; /*!<Set True if this GOOSE CB is enabled */
	char* gocbRef; /*!<A pointer to the GOOSE Control Blocks Reference */
	Boolean isPublisher; /*!<Set True if this is a GOOSE Publisher control block, FALSE if this is a subscriber */
	IEC61850_DataAttributeID** daidArray; /*!<Array of Private IDs */
	U32 daidArraySize; /*!<The numebr of elements in the daidArray; */
} GOOSEControlBlocks;

/*!	\brief	数据属性信息
用作 `IEC61850_GetDataAttributesInfo()` 接口的响应数据。<br>
客户端调用 `IEC61850_GetDataAttributesInfo()` 接口，响应数据中的 `DAData` 中不包含数据值（`DAData.pvData` 为 NULL），`name` 
为数据属性从逻辑设备名称开始的相对引用，其中的数据属性连接符是 `$` ，例如 "CSWI0.Pos\$stVal"；<br>
服务端调用 `IEC61850_GetDataAttributesInfo()` 接口，响应数据中的 `DAData` 中会附带数据值，`name` 为数据属性的 ObjectName，例如 "stVal"。<br>
*/
typedef struct DAInfo
{
	IEC61850_DataAttributeID* DAID;		/*!< 数据属性ID（DAID） */
	IEC61850_DataAttributeData DAData;	/*!< 数据属性值 */
	char* name;							/*!< 数据属性名称 */
} DAInfo;

/*! 原因码。用于指示控制块上报或记录数据的触发原因。实际的取值，与控制块的 "触发条件" 相对应。
\see IEC61850-8-1 section 8.1.3.11 */
typedef enum IEC61850_ReasonCode
{
	IEC61850_RESERVED = 0x80,			/*!< 保留值（Reserved） */
	IEC61850_DATA_CHANGE = 0x40,		/*!< 数据变化（data-change） */
	IEC61850_QUALITY_CHANGE = 0x20,		/*!< 质量变化（quality-change） */
	IEC61850_DATA_UPDATE = 0x10,		/*!< 数据更新（data-update） */
	IEC61850_INTEGRITY = 0x08,			/*!< 完整性周期（integrity） */
	IEC61850_GENERAL_INTERROGATION = 0x04, /*!< 总召唤（GI） */
	IEC61850_APPLICATION_TRIGGER = 0x02,/*!< 应用触发（application-trigger）<br>该值仅适用于日志控制块，不适用于其他类别的控制块。<br>由应用触发的日志，应该由应用保证创建规范一致的日志条目，日志的数据内容也由应用提供。 */
} IEC61850_ReasonCode;

/*! \brief 日志条目数据 */
typedef struct IEC61850_LogEntryData
{
	// IEC61850_DataAttributeID* logValueDAID; /*!< 条目数据对应的数据属性ID。<br>如果没有，则该值为 NULL。 */
	IEC61850_DataAttributeData  logValue;	/*!< 数据的值 */
	char DataRef[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 数据的引用 */
	char FC[3];								/*!< 功能约束 */
	IEC61850_ReasonCode reasonCode;		/*!< 日志触发原因码 */
} IEC61850_LogEntryData;

/*! \brief 日志条目 */
typedef struct IEC61850_LogEntry
{
	U8					entryId[8];			/*!< 日志条目ID */
	IEC61850_TimeStamp	entryTime;			/*!< 日志条目时间 */
	IEC61850_LogEntryData* logEntryData;	/*!< 日志条目数据。
											内容为 struct #IEC61850_LogEntryData 的数组，元素数量由 numberOfLogEntryData 成员指定。 */
	U32					numOfLogEntryData;	/*!< logEntryData 中的日志条目数量 */
} IEC61850_LogEntry;

/*! \brief 日志条目列表 */
typedef struct IEC61850_LogEntries
{
	IEC61850_LogEntry*	entries;			/*!< 日志条目列表。内容为 struct IEC61850_LogEntry 的数组，元素数量由 numberOfEntries 成员指定。 */
	U32					numOfEntries; 		/*!< 日志条目数量 */
	Boolean 			moreFollows;		/*!< moreFollows */
} IEC61850_LogEntries;

/*!  \brief 日志状态值 */
typedef struct IEC61850_LogStatus
{
	IEC61850_TimeStamp OldestEntryTime;		/*!< 最老条目的条目时间 */
	IEC61850_TimeStamp NewestEntryTime;		 /*!< 最新条目的条目时间 */
	U32 OldestEntry;  /*!< 最老条目的条目ID（EntryID） */
	U32 NewestEntry;  /*!< 最老条目的条目ID（EntryID） */
} IEC61850_LogStatus;

/*! \brief 读日志状态值的响应结果 */
typedef struct IEC61850_GetLogStatus_Result
{
	int errorCode;		/*!< 服务错误。实际值为 ServiceError 的枚举值。 */
	IEC61850_LogStatus* logStatus;	/*!< 日志状态值。
						errorCode = SERVICE_ERROR_NO_ERROR (0) logStatus 参数有效；
						errorCode ≠ SERVICE_ERROR_NO_ERROR (0) 时，该参数为 NULL */
} IEC61850_GetLogStatus_Result;

/*! \brief 读日志状态值的响应结果列表 */
typedef struct IEC61850_GetLogStatus_ResultList
{
	U32 size;		/*!< 数据的值 */
	IEC61850_GetLogStatus_Result* logStatusResults;	/*!< 读日志状态值的响应结果列表。内容为 struct #IEC61850_GetLogStatus_Result 的数组，元素数量由 size 成员指定 */
} IEC61850_GetLogStatus_ResultList;

/*! \brief 日志查询参数结构体 */
typedef struct LogQueryParam
{
	char LogRef[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 日志控制块引用路径 */
	struct TimeOfDay* StartTime;					/*!< 查询起始时间指针(可为NULL表示不限制) */
	struct TimeOfDay* StopTime;						/*!< 查询结束时间指针(可为NULL表示不限制) */
	U32 entryId;									/*!< 查询起始条目ID(0表示从最新条目开始) */
} LogQueryParam;

/*!  \brief 数据的引用和定义 */
typedef struct DataRefValue
{
	char* dataRef;								/*!< 数据的引用 */
	IEC61850_DataAttributeData dataAttribute;	/*!< 数据值 */
} DataRefValue;

/*!  \brief 数据属性列表 */
typedef struct IEC61850_DataAttributeValues
{
	U32 length;						/*!< 数据数量 */
	DataRefValue* dataRefValueList;	/*!< 数据的引用和值。<br>内容为 `struct DataRefValue` 的数组，元素数量由 `length` 成员指定 */
} IEC61850_DataAttributeValues;

/*!  \brief 数据定义 */
typedef struct DataDefinition
{
	eDataTypeCMS eType;							/*!< 基本数据类型 */
	int arraySize;								/*!< 数组元素数量。<br>仅在数据类型 `eType` 为数组 `DATA_TYPE_ARRAY` 时为数组元素数量，否则为 0 */
	int structSize;								/*!< 结构体成员数量。<br>仅在数据类型 `eType` 为结构体 `DATA_TYPE_STRUCTURE` 时，该值为结构体成员数量，否则为 0 */
	struct DataDefinition* arrayDefinition;		/*!< 数组元素数据的定义。<br>需要进一步解析。 */
	struct StructDefinition* structDefinition;	/*!< 结构体成员数据的定义<br>需要基于 `structSize` 指定的数量继续遍历解析 */
	unsigned int stringSize;					/*!< 字符串长度。<br>仅在数据类型 `eType` 为字符串类型（`#DATA_TYPE_BIT_STRING` \|  `#DATA_TYPE_OCTET_STRING` \| `#DATA_TYPE_VISIBLE_STRING` \| `#DATA_TYPE_UNICODE_STRING` \|时，该值为字符串长度值，否则为 0 */
} DataDefinition;

/*!  \brief 结构体成员的定义 */
typedef struct StructDefinition
{
	char name[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 结构体成员名称 */
	char FC[3];									/*!< 结构体成员的功能约束 */
	DataDefinition definition;					/*!< 结构体成员的数据定义 */
} StructDefinition;

/*!	\brief	数据定义。包含数据引用，以及公共数据类类型。 */
typedef struct DataRefDefinition
{
	char dataRef[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 数据的引用 */
	char sCDC[CDC_STRING_LEN];						/*!< 公共数据类 */
	DataDefinition definition;						/*!< 数据定义 */
} DataRefDefinition;

/*!	\brief	数据定义列表 */
typedef struct DataDefinitions
{
	U32 length;									/*!< 数据数量 */
	DataRefDefinition* dataRefDefinitionList;	/*!< 数据定义列表<br>内容为 `struct DataRefDefinition` 的数组，元素数量由 `length` 成员指定 */
} DataDefinitions;

typedef struct DataItemList
{
	U32 length;
	struct tDataItem* dataItems;
} DataItemList;

/*!	\brief	数据值列表 */
typedef struct DataValsList
{
	U32 length;									/*!< 数据数量 */
	IEC61850_DataAttributeData* dataAttributes;	/*!< 内容为 struct #IEC61850_DataAttributeData 的数组，元素数量由 length 成员指定 */
} DataValsList;

/*!	\brief	数据属性值	 */
typedef struct FCDAVals
{
	char dataRef[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 数据引用 */
	char FC[3];										/*!< 功能约束 */
	IEC61850_DataAttributeData dataAttributes;		/*!< 数据值 */
} FCDAVals;

/*\brief 报告控制块的可选域。这里将可选域 BIT STRING 的每个 bit 位，拆分为了多个对位意义的 Boolean 类型的值。
值为 TRUE/FALSE 代表报告中 包含/不包含 对应的可选域。 */
typedef struct RCBOptFlds
{
	Boolean sequence_number;		/*!< 序列号 */
	Boolean report_time_stamp;		/*!< 报告时标（report-time-stamp） */
	Boolean reason_for_inclusion;	/*!< 包含原因（reason-for-inclusion）。即原因码（ReasonCode） */
	Boolean data_set_name;			/*!< 数据集名称（data-set-name） */
	Boolean data_reference;			/*!< 数据引用（data-reference） */
	Boolean buffer_overflow;		/*!< 缓存区溢出（buffer-overflow） */
	Boolean entryId;				/*!< 条目标识（entryID） */
	Boolean conf_revision;			/*!< 配置版本（conf-revision） */
	Boolean segmentation;			/*!< 分段（Segmentation）<br>该可选域为弃用的可选域，应始终为 FALSE。 */
} RCBOptFlds;

/*!	\brief	报告控制块的触发条件。这里将触发条件 BIT STRING 的每个 bit 位，拆分为了多个对位意义的 Boolean 类型的值。
值为 TRUE/FALSE 代表报告控制块 已启用/未启用 对应的触发选项。  */
typedef struct RCBTriggerConditions
{
	Boolean reserved;				/*!< 保留（reserved）。**禁止使用。**（忽略成员命名错误） */
	Boolean data_change;			/*!< 数据变化触发 */
	Boolean quality_change;			/*!< 质量变化触发 */
	Boolean data_update;			/*!< 数据更新触发 */
	Boolean integrity;				/*!< 完整性周期触发 */
	Boolean general_interrogation;	/*!< 总召唤触发 */
} RCBTriggerConditions;

/*! \brief 报告控制块(RCB)参数结构体 */
typedef struct RCBValues
{
	U8 rptId[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 报告控制块引用路径 */
	Boolean bufferFlag;							/*!< 缓冲标志(true=启用报告缓冲) */
	Boolean rptEna;								/*!< 报告使能标志(true=启用报告) */
	U8 datSet[DATASET_NAME_SIZE + 1];			/*!< 关联的数据集名称 */
	U32 confRev;								/*!< 配置版本号 */
	U16 optFlds;								/*!< 报告选项域 */
	U32 bufTm;									/*!< 缓冲时间(毫秒) */
	U16 sqNum;									/*!< 序列号 */
	U8 trgOps;									/*!< 触发条件 */
	U32 intgPd;									/*!< 完整性周期(毫秒) */
	Boolean gi;									/*!< 总召唤标志(true=触发总召唤) */
	U8 owner[64];								/*!< 所有者标识 */
	Boolean purgeBuf;							/*!< 清除缓冲区标志(true=清除) */
	U8 entryId[8];								/*!< 条目唯一标识 */
	IEC61850_TimeStamp timeOfEntry;				/*!< 条目时间戳 */
	U16 resvTms;								/*!< 保留时间(秒) */
	Boolean resv;								/*!< 保留标志 */
} RCBValues;

/*\brief 读报告控制块值的响应结果 */
typedef struct ReturnRCBValues
{
	eServiceError serviceError;	/*!< 服务错误。实际值为 #eServiceError 。<br> 读报告控制块值成功时，该值为 SERVICE_ERROR_NO_ERROR (0：无差错)，否则为非 0 值的 #eServiceError */
	RCBValues* rcbValues;		/*!< 报告控制块值。读报告控制块值成功时，该值有效，否则为 NULL */
} ReturnRCBValues;

/*! \brief 报告控制块参数设置标志枚举 */
typedef enum eSetFlag
{
	RPT_ID = 0,		/*!< 报告控制块引用路径标识 */
	RPT_ENA = 1,	/*!< 报告使能标志标识 */
	DAT_SET = 2,	/*!< 关联数据集名称标识 */
	OPT_FLDS = 3,	/*!< 选项字段位掩码标识 */
	BUF_TM = 4,		/*!< 缓冲时间(毫秒)标识 */
	TRG_OPS = 5,	/*!< 触发条件位掩码标识 */
	INTG_PD = 6,	/*!< 完整性周期(毫秒)标识 */
	GI = 7,			/*!< 总召唤标志标识 */
	PURGE_BUF = 8,	/*!< 清除缓冲区标志标识 */
	RESV = 8,		/*!< 保留标志标识(与PURGE_BUF共享值) */
	ENTRY_ID = 9,	/*!< 条目唯一标识符标识 */
	RESV_TMS = 10,	/*!< 保留时间(秒)标识 */
} eSetFlag;

/*\brief 设置的报告控制块值的请求参数 */
typedef struct SetRCBValues
{
	char setFlag[15];	/*!< 设置属性标记。
							用于标记报告控制块中的哪些属性有被请求设置。
							有被设置的控制块属性，需要按照属性的索引值，设置 setFlag 中对应索引的元素值为 1，反之则设置为 0 。
							属性的索引值从 0 开始计，
							对于 BRCB，使用前 11 个元素来标记，setFlag[0] ~ setFlag[10] 依次代表设置属性：rptID、rptEna、datSet、optFlds、bufTm、trgOps、intgPd、gi、purgeBuf、entryID、resvTms；
							对于 URCB，使用前 9 个元素来标记，setFlag[0] ~ setFlag[8] 依次代表设置属性：rptID、rptEna、datSet、optFlds、bufTm、trgOps、intgPd、gi、resv
						*/
	char sRCBRef[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 报告控制块的引用 */
	RCBValues rcbValues;							/*!< 报告控制块的值 */
} SetRCBValues;

/*\brief 服务错误列表 */
typedef struct ServiceErrorList
{
	U32 length;		/*!< 数据数量 */
	int* serErrs;	/*!< 服务错误列表内容为 #eServiceError 的数组，元素数量由 length 成员指定 */
} ServiceErrorList;

/*\brief 定值组控制块的值 */
typedef struct SGCBValues
{
	U8 numOfSG;					/*!< 定值的组数		  [1] IMPLICIT INT8U */
	U8 actSG;					/*!< 激活的定值组号   [2] IMPLICIT INT8U */
	U8 editSG;					/*!< 编辑的定值组号   [3] IMPLICIT INT8U */
	IEC61850_TimeStamp lActTm;	/*!< 最后的激活时间   [4] IMPLICIT TimeStamp */
	U16 resvTms;				/*!< 定值组编辑的保留时间 [5] IMPLICIT INT16U OPTIONAL */
} SGCBValues;

/*\brief 读定值组控制块值的响应结果 */
typedef struct ReturnSGCBValues
{
	int errorCode;				/*!< 服务错误。实际值为 #eServiceError 。读定值组控制块值成功时，该值为 #SERVICE_ERROR_NO_ERROR (0：无差错)，否则为非 0 值的 eServiceError */
	SGCBValues* sgcbValues;		/*!< 定值组控制块值。读定值组控制块值成功时，该值有效，否则为 NULL */
} ReturnSGCBValues;

/*\brief 读定值组控制块值的响应结果列表 */
typedef struct SGCBValuesList
{
	unsigned int length;	/*!< 定值组数量 */
	ReturnSGCBValues* list;	/*!< 读定值组控制块值的响应结果列表。内容为 struct ReturnSGCBValues 的数组，元素数量由 length 成员指定 */
} SGCBValuesList;

/*\brief 日志控制块的值 */
typedef struct LCBValues
{
	Boolean logEna;				/*!< 使能标记  TRUE：使能   FALSE：未使能 */
	char datSet[OBJECT_REFERENCE_STRING_LEN + 1];  /*!< 控制块关联的数据集引用 */
	char trgOps;				/*!< 触发条件。
									触发条件的定义为 BIT STRING(SIZE(6))。
									取其最高的 6 个 bit 位来使用，
									最高位记为 bit 0，各 bit 位的含义依次为：
									bit 0：保留（reserved）
									bit 1：数据变化触发（data-change）
									bit 2：质量变化触发（quality-change）
									bit 3：数据更新触发（data-update）
									bit 4：完整性周期触发（integrity）
									bit 5：总召唤触发（general-interrogation） */
	U32 intgPd;					/*!< 完整性周期 */
	char logRef[OBJECT_REFERENCE_STRING_LEN + 1];	 /*!< 存储日志的引用 */
	char optFlds;				/*!< 可选域。
									日志控制块的可选域为 BIT STRING(SIZE(1))，
									内容为 "包含原因（reason-for-inclusion）" */
	U32 bufTm;					/*!< 缓存时间 */
} LCBValues;

/*\brief 读日志控制块值的响应结果 */
typedef struct ReturnLCBValues
{
	int errorCode;				/*!< 服务错误。实际值为 #eServiceError 。
									读日志控制块值成功时，该值为 #SERVICE_ERROR_NO_ERROR (0：无差错)，否则为非 0 值的 #eServiceError */
	LCBValues* lcbValues;		/*!< 日志控制块值。读日志控制块值成功时，该值有效，否则为 NULL */
} ReturnLCBValues;

/*! \brief 读日志控制块值的响应结果列表 */
typedef struct LCBValuesList
{
	unsigned int length;	/*<\ 控制块数量 */
	ReturnLCBValues* list;	/*<\ 读日志控制块值的响应结果列表  内容为 struct #ReturnLCBValues 的数组，元素数量由 length 成员指定 */
} LCBValuesList;

/*! \brief 设置日志控制块值的请求参数 */
typedef struct tSetLCBValues
{
	char setFlag[7];			/*!< 设置属性标记。
									 用于标记日志控制块中的哪些属性有被请求设置。
									 有被设置的控制块属性，需要设置 setFlag 中对应元素的值为 1，反之则设置为 0 。
									 setFlag[0] ~ setFlag[6] 依次代表设置属性：logEna、datSet、optFlds、intgPd、logRef、trgOps、bufTm */
	char lcbRef[OBJECT_REFERENCE_STRING_LEN + 1]; /*!< 日志控制块的引用 */
	LCBValues lcbValues;		/*!< 日志控制块的值 */
} tSetLCBValues;

/*! \brief 设置日志控制块值的请求参数列表 */
typedef struct tSetLcbValuesList
{
	unsigned int length;	/*!< 响应结果的数量。与请求设置的日志控制块数量一致。 */
	tSetLCBValues* list;	/*!< 设置日志控制块值的请求参数列表。  内容为 struct SetLCBValues 的数组，元素数量由 length 成员指定 */
} tSetLcbValuesList;

/* \brief SetLCBValues 请求的 LCB 可选字段索引 */
typedef enum eSetLCBRequest
{
	SET_LCB_REQ_LOG_ENA = 0,	/*!< 日志使能标志设置索引 */
	SET_LCB_REQ_DAT_SET = 1,	/*!< 关联数据集名称设置索引 */
	SET_LCB_REQ_TRG_OPS = 2,	/*!< 触发操作条件设置索引 */
	SET_LCB_REQ_INTG_PD = 3,	/*!< 完整性周期设置索引(毫秒) */
	SET_LCB_REQ_LOG_REF = 4,	/*!< 日志控制块引用设置索引 */
	SET_LCB_REQ_OPT_FLDS = 5,	/*!< 选项字段位掩码设置索引 */
	SET_LCB_REQ_BUF_TM = 6		/*!< 缓冲时间设置索引(毫秒) */
} eSetLCBRequest;

/*! \brief 日志控制块参数设置结果状态枚举 */
typedef enum eSetLCBResult
{
	SET_LCB_RESULT_ERROR = 0,		/*!< 参数设置失败(通用错误状态) */
	SET_LCB_RESULT_LOG_ENA = 1,		/*!< 日志使能标志设置成功 */
	SET_LCB_RESULT_DAT_SET = 2,		/*!< 数据集引用设置成功 */
	SET_LCB_RESULT_TRG_OPS = 3,		/*!< 触发操作条件设置成功 */
	SET_LCB_RESULT_INTG_PD = 4,		/*!< 完整性周期设置成功 */
	SET_LCB_RESULT_LOG_REF = 5,		/*!< 日志控制块引用设置成功 */
	SET_LCB_RESULT_OPT_FLDS = 6,	/*!< 选项字段位掩码设置成功 */
	SET_LCB_RESULT_BUF_TM = 7		/*!< 缓冲时间参数设置成功 */
} eSetLCBResult;

/* \brief 设置日志控制块值的响应结果 */
typedef struct tSetLCBErrors
{
	int		resultError[8];	/*!< 设置日志控制块值的响应结果。<br>其中，<br>
								resultError[0] 代表请求设置的日志控制块引用有效无效；<br>
								resultError[1] ~ resultError[7] 依次代表设置日志控制块 logEna、datSet、optFlds、intgPd、logRef、trgOps、bufTm 属性值的响应结果。<br>
								全部元素值均为 `#SERVICE_ERROR_NO_ERROR` (0) 时，代表响应为肯定响应；<br>
								任意元素值不为 `#SERVICE_ERROR_NO_ERROR` (0) 时，代表响应为否定响应。<br>
								resultError[0] ≠ `SERVICE_ERROR_NO_ERROR` 时，resultError[1] ~ resultError[11] 无意义。 */
	Boolean	errorFlag[8];	/*!< 被设置的日志控制块属性对应的响应结果标记。<br>
								用于标记 `resultError` 成员中对应索引的元素是否有意义。<br>
								其中， errorFlag[0] 代表 resultError[0] 是否有效。<br>
								errorFlag[1] ~ errorFlag[7] 中值为 TRUE 的元素，代表 SetLCBValues 有请求设置对应的控制块属性，对应索引的 `resultError` 成员元素有意义；<br>
								errorFlag[1] ~ errorFlag[7] 中值为 FALSE 的元素，为没有请求设置的属性，对应索引的 `resultError` 成员元素无意义。<br>
								errorFlag[1] ~ errorFlag[7] 依次代表控制块属性 logEna、datSet、optFlds、intgPd、logRef、trgOps、bufTm。<br>
								errorFlag[0] = TRUE 时， errorFlag[1] ~ errorFlag[7] 无意义，仅需确认 resultError[0]，无需确认 resultError[1] ~ resultError[7] */
} tSetLCBErrors;

/* \brief 设置日志控制块值的响应结果列表 */
typedef struct SetLCBErrorList
{
	unsigned int length;	/*!< 响应结果的数量。与请求设置的日志控制块数量一致。 */
	tSetLCBErrors* list;	/*!< 设置日志控制块值的响应结果列表  内容为 struct tSetLCBErrors 的数组，元素数量由 length 成员指定 */
} SetLCBErrorList;

/*! \brief GOOSE控制块成员偏移量列表结构体 */
typedef struct GoCBMemberOffsetList
{
	U32 size;           /*!< 成员偏移量数组的元素个数 */
	U16* memberOffset;  /*!< 指向成员偏移量数组的指针 */
} GoCBMemberOffsetList;

/* \brief GOOSE控制块的值 */
typedef struct GoCBValues
{
	Boolean goEna;		/*!<  使能标记  TRUE：使能		FALSE：未使能 */
	char goID[VISIBLE_STRING_129_LEN + 1];	/*!< GOOSE控制块的ID */
	char datSet[OBJECT_REFERENCE_STRING_LEN + 1]; /*!< 控制块关联的数据集引用 */
	U32 confRev;		/*!< 配置版本号 */
	Boolean ndsCom;		/*!< "需要重新配置" 标记 */
	U8 addr[6];			/*!< 地址 */
	U8 priority;		/*!< 优先级 */
	U16 vid;			/*!< VLAN ID */
	U16 appid;			/*!< 应用ID */
} GoCBValues;

/* \brief 读 GOOSE 控制块值的响应结果 */
typedef struct ReturnGoCBValues
{
	eServiceError errorCode;	/*!<  服务错误。实际值为 #eServiceError 。
									读 GOOSE 控制块值成功时，该值为 #SERVICE_ERROR_NO_ERROR (0：无差错)，否则为非 0 值的 ServiceError */
	GoCBValues* cbValues;		/*!< GOOSE 控制块值。读 GOOSE 控制块值成功时，该值有效，否则为 NULL */
} ReturnGoCBValues;

/* \brief 读 GOOSE 控制块值的响应结果列表 */
typedef struct GoCBValuesList
{
	unsigned int length;	/*!< 控制块数量 */
	ReturnGoCBValues* list;	/*!< 读 GOOSE 控制块值的响应结果列表。内容为 struct #ReturnGoCBValues 的数组，元素数量由 length 成员指定 */
} GoCBValuesList;

/* \brief GOOSE控制块参数设置标志位枚举 */
typedef enum eSetGoCBFlag
{
	SET_GOCB_FLAG_GO_ENA = 0,	/*!< GOOSE使能标志 */
	SET_GOCB_FLAG_GO_ID = 1,	/*!< GOOSE ID标志 */
	SET_GOCB_FLAG_DAT_SET = 2,	/*!< 关联数据集引用标志 */
} eSetGoCBFlag;

/* \brief 设置 GOOSE 控制块值的请求参数 */
typedef struct tSetGoCBValues
{
	char setFlag[4];	/*!< 设置属性标记。
							用于标记 GOOSE 控制块中的哪些属性有被请求设置。
							有被设置的控制块属性，需要设置 setFlag 中对应元素的值为 1，反之则设置为 0 。
							setFlag[0] ~ setFlag[2] 依次代表设置属性：goEna、goID、datSet。
							setFlag[3] 未使用 */
	char ref[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< GOOSE 控制块的引用 */
	Boolean goEna;		/*!<  使能标记  TRUE：使能		FALSE：未使能 */
	char goID[VISIBLE_STRING_129_LEN + 1];	/*!< GOOSE控制块的ID */
	char datSet[OBJECT_REFERENCE_STRING_LEN + 1]; /*!< 控制块关联的数据集引用 */
} tSetGoCBValues;

/* \brief GOOSE控制块参数设置结果状态枚举 */
typedef enum eSetGoCBResult
{
	SET_GOCB_RESULT_ERROR = 0,		/*!< 参数设置失败(通用错误状态) */
	SET_GOCB_RESULT_GO_ENA = 1,		/*!< GOOSE使能标志设置成功 */
	SET_GOCB_RESULT_GO_ID = 2,		/*!< GOOSE标识符设置成功 */
	SET_GOCB_RESULT_DAT_SET = 3,	/*!< 关联数据集引用设置成功 */
} eSetGoCBResult;


/* \brief 设置 GOOSE 控制块值的响应结果 */
typedef struct SetGoCBErrors
{
	eServiceError resultError[4];	/*!< 设置 GOOSE 控制块值的响应结果。
				其中，
				resultError[0] 代表请求设置的 GOOSE 控制块引用有效无效；
				resultError[1] ~ resultError[3] 依次代表设置 GOOSE 控制块 goEna、goID、datSet 属性值的响应结果。

				全部元素值均为 SERVICE_ERROR_NO_ERROR (0) 时，代表响应为肯定响应；
				任意元素值不为 SERVICE_ERROR_NO_ERROR (0) 时，代表响应为否定响应。
				resultError[0] ≠ SERVICE_ERROR_NO_ERROR 时，resultError[1] ~ resultError[3] 无意义。 */
	Boolean	errorFlag[4];	/*!< 被设置的 GOOSE 控制块属性对应的响应结果标记。
				用于标记 resultError 成员中对应索引的元素是否有意义。
				其中，
				errorFlag[0] 代表 resultError[0] 是否有效。
				errorFlag[1] ~ errorFlag[3] 中值为 TRUE 的元素，代表 SetGoCBValues 有请求设置对应的控制块属性，对应索引的 resultError 成员元素有意义；
				errorFlag[1] ~ errorFlag[3] 中值为 FALSE 的元素，为没有请求设置的属性，对应索引的 resultError 成员元素无意义。
				errorFlag[1] ~ errorFlag[3] 依次代表控制块属性 goEna、goID、datSet。

				errorFlag[0] = TRUE 时， errorFlag[1] ~ errorFlag[3] 无意义，仅需确认 resultError[0]，无需确认 resultError[1] ~ resultError[3] */
}SetGoCBErrors;

/* \brief 设置 GOOSE 控制块值的响应结果列表 */
typedef struct SetGocbErrorList
{
	unsigned int length;	/*!< 响应结果的数量。与请求设置的 GOOSE 控制块数量一致。 */
	SetGoCBErrors* list;	/*!< 设置 GOOSE 控制块值的响应结果列表。内容为 SetGoCBErrors 的数组，元素数量由 length 成员指定 */
} SetGocbErrorList;

/*\brief  */
typedef enum SampleMode
{
	SMP_MOD_SAMPLES_PER_NOMINAL_PERIOD = 0,	/*!< 0: samples-per-nominal-period */
	SMP_MOD_SAMPLES_PER_SECOND = 1,			/*!< 1: samples-per-second */
	SMP_MOD_SECONDS_PER_SAMPLE = 2			/*!< 2: seconds-per-sample  */
} SampleMode;

/*\brief 多播采样值控制块的值 */
typedef struct MSVCBValues
{
	Boolean svEna;		/*!< 使能标记  TRUE：使能   FALSE：未使能 */
	char msvID[VISIBLE_STRING_129_LEN + 1];  /*!< 多播采样值控制块的ID */
	char datSet[OBJECT_REFERENCE_STRING_LEN + 1]; /*!< 控制块关联的数据集引用 */
	U32 confRev;	/*!< 配置版本号 */
	S8 smpMod;		/*!< 采样模式。
						0：samples-per-nominal-period
						1：samples-per-second
						2：seconds-per-sample */
	U16 smpRate;	/*!< 采样率 */
	char optFlds;	/*!< 可选域。
						多播采样值控制块的可选域定义为 BIT STRING(SIZE(5))
						取其最高的 5 个 bit 位来使用，
						最高位记为 bit 0，各 bit 位的含义依次为：
						bit 0：刷新时间（refresh-time）
						bit 1：保留（reserved）
						bit 2：采样率（sample-rate）
						bit 3：数据集名称（data-set-name）
						bit 4：安全（security） */
	U8 addr[6];		/*!< 地址 */
	U8 priority;	/*!< 优先级 */
	U16 vid;		/*!< VLAN ID */
	U16 appid;		/*!< 应用ID */
} MSVCBValues;

/*\brief 读多播采样值控制块值的响应结果 */
typedef struct ReturnMSVCBValues
{
	int errorCode;	/*!< 服务错误。实际值为 #eServiceError 。
					读多播采样值控制块值成功时，该值为 #SERVICE_ERROR_NO_ERROR (0：无差错)，否则为非 0 值的 #eServiceError */
	MSVCBValues* cbValues;	/*!< GOOSE 控制块值。读多播采样值控制块值成功时，该值有效，否则为 NULL */
} ReturnMSVCBValues;

/*\brief 读多播采样值控制块值的响应结果列表 */
typedef struct MSVCBValuesList
{
	unsigned int length;		/*!< 控制块数量 */
	ReturnMSVCBValues* list;	/*!< 读多播采样值控制块值的响应结果列表。内容为 struct #ReturnMSVCBValues 的数组，元素数量由 length 成员指定 */
} MSVCBValuesList;

/*\brief SetMSVCB标识 */
typedef enum eSetMSVCBFlag
{
	SET_MSVCB_FLAG_SV_ENA = 0,		/*!< SV使能标志设置位(0-禁用 1-启用) */
	SET_MSVCB_FLAG_MSV_ID = 1,		/*!< 多播采样值标识符设置位 */
	SET_MSVCB_FLAG_DAT_SET = 2,		/*!< 关联数据集引用设置位 */
	SET_MSVCB_FLAG_SMP_MOD = 3,		/*!< 采样模式设置位(0-基于时间 1-基于事件) */
	SET_MSVCB_FLAG_SMP_RATE = 4,	/*!< 采样率设置位(单位：采样点数/周期) */
	SET_MSVCB_FLAG_OPT_FLDS = 5		/*!< 可选字段配置设置位(位掩码方式) */
} eSetMSVCBFlag;

/*\brief 设置多播采样值控制块值的请求参数 */
typedef struct tSetMSVCBValues
{
	char setFlag[6];	/*!< 设置属性标记。
						用于标记多播采样值控制块中的哪些属性有被请求设置。
						有被设置的控制块属性，需要设置 setFlag 中对应元素的值为 1，反之则设置为 0 。
						setFlag[0] ~ setFlag[5] 依次代表设置属性：svEna、msvID、datSet、smpMod、smpRate、optFlds */
	char ref[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 多播采样值控制块的引用 */
	Boolean svEna;	/*!< 使能标记	TRUE：使能	FALSE：未使能 */
	char msvID[VISIBLE_STRING_129_LEN + 1];			/*!< 多播采样值控制块的ID */
	char datSet[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 控制块关联的数据集引用 */
	S8 smpMod;		/*!< 采样模式。
						0：samples-per-nominal-period
						1：samples-per-second
						2：seconds-per-sample */
	U16 smpRate;	/*!< 采样率 */
	char optFlds;	/*!< 可选域。
						多播采样值控制块的可选域定义为 BIT STRING(SIZE(5))
						取其最高的 5 个 bit 位来使用，
						最高位记为 bit 0，各 bit 位的含义依次为：
						bit 0：刷新时间（refresh-time）
						bit 1：保留（reserved）
						bit 2：采样率（sample-rate）
						bit 3：数据集名称（data-set-name）
						bit 4：安全（security） */
} tSetMSVCBValues;

/*\brief 采样值控制块参数设置结果状态枚举 */
typedef enum eSetMSVCBResult
{
	SET_MSVCB_RESULT_ERROR = 0,		/*!< 通用错误状态(参数越界/权限不足等) */
	SET_MSVCB_RESULT_SV_ENA = 1,	/*!< SV使能标志设置成功 */
	SET_MSVCB_RESULT_MSV_ID = 2,	/*!< 多播采样值标识符设置成功 */
	SET_MSVCB_RESULT_DAT_SET = 3,	/*!< 关联数据集引用设置成功 */
	SET_MSVCB_RESULT_SMP_MOD = 4,	/*!< 采样模式设置成功 */
	SET_MSVCB_RESULT_SMP_RATE = 5,	/*!< 采样率参数设置成功 */
	SET_MSVCB_RESULT_OPT_FLDS = 6	/*!< 可选字段配置设置成功 */
} eSetMSVCBResult;


/*\brief 设置多播采样值控制块值的响应结果 */
typedef struct SetMSVCBErrors
{
	Boolean errorFlag[7];	/*!< 被设置的多播采样值控制块属性对应的响应结果标记。
							用于标记 #resultError 成员中对应索引的元素是否有意义。
							其中，
							errorFlag[1] ~ errorFlag[6] 中值为 TRUE 的元素，代表 SetMSVCBValues 有请求设置对应的控制块属性，对应索引的 #resultError 成员元素有意义；
							errorFlag[1] ~ errorFlag[6] 中值为 FALSE 的元素，为没有请求设置的属性，对应索引的 #resultError 成员元素无意义。
							errorFlag[1] ~ errorFlag[6] 依次代表控制块属性 svEna、msvID、datSet、smpMod、smpRate、optFlds。
							errorFlag[0] = TRUE 时， errorFlag[1] ~ errorFlag[6] 无意义，仅需确认 resultError[0]，无需确认 resultError[1] ~ resultError[6] */
	int resultError[7];		/*!< 设置多播采样值控制块值的响应结果。
							其中，resultError[1] ~ resultError[6] 依次代表设置多播采样值控制块 svEna、msvID、datSet、smpMod、smpRate、optFlds 属性值的响应结果。
							全部元素值均为 #SERVICE_ERROR_NO_ERROR (0) 时，代表响应为肯定响应；
							任意元素值不为 #SERVICE_ERROR_NO_ERROR (0) 时，代表响应为否定响应。
							resultError[0] ≠ SERVICE_ERROR_NO_ERROR 时，resultError[1] ~ resultError[6] 无意义。 */
}SetMSVCBErrors;

/*\brief 设置多播采样值控制块值的响应结果列表 */
typedef struct SetMSVCBErrorList
{
	unsigned int length;	/*!< 响应结果的数量。与请求设置的多播采样值控制块数量一致。 */
	SetMSVCBErrors* list;	/*!< 设置多播采样值控制块值的响应结果列表。内容为 SetMSVCBErrors 的数组，元素数量由 length 成员指定 */
} SetMSVCBErrorList;

/*\brief ACSI 服务接口 GetAllCBValues 的响应数据。控制块值列表。 */
typedef struct GetAllCBValsReturn
{
	U32				numOfCB;	/*!< 控制块数量  代表响应的控制块数量 */
	char**			SubRefList;	/*!< 控制块的子引用（SubReference）列表。元素数量由 numOfCB 指示。 */
	RCBValues*		brcbValues;	/*!< 缓存报告控制块列表。
									请求的 ACSIClass 为 BRCB 时，该值有效，否则为 NULL。
									有效时，RCBValues 的数量由 numOfCB 指示。 */
	RCBValues*		urcbValues;	/*!< 非缓存报告控制块列表。
									请求的 ACSIClass 为 URCB 时，该值有效，否则为 NULL。
									有效时，RCBValues 的数量由 numOfCB 指示。 */
	SGCBValues*		sgcbValues;	/*!< 定值组控制块列表。
									请求的 ACSIClass 为 SGCB 时，该值有效，否则为 NULL。
									有效时，SGCBValues 的数量由 numOfCB 指示。 */
	LCBValues*		lcbValues;	/*!< 日志控制块列表。
									请求的 ACSIClass 为 LCB 时，该值有效，否则为 NULL。
									有效时，LCBValues 的数量由 numOfCB 指示。 */
	GoCBValues*		goCBValues;	/*!< 	GOOSE控制块列表。
									请求的 ACSIClass 为 GoCB 时，该值有效，否则为 NULL。
									有效时，GoCBValues 的数量由 numOfCB 指示。 */
	MSVCBValues*	svCBValues;	/*!< 	多播采样值控制块列表。
									请求的 ACSIClass 为 MSVCB 时，该值有效，否则为 NULL。
									有效时，MSVCBValues 的数量由 numOfCB 指示。 */
} GetAllCBValsReturn;

/*\brief 带功能约束的数据引用 */
typedef struct FCDA
{
	char DARef[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 数据引用 */
	char FC[3];										/*!< 功能约束 */
} FCDA;

/*\brief 带功能约束的数据引用列表 */
typedef struct FCDAList
{
	U32 size;		/*!< 数据数量 */
	FCDA* FCDAs;	/*!< 带功能约束的数据引用列表   内容为 struct FCDA 的数组，元素数量由 numOfFCDA 成员指定 */
} FCDAList;

/*\brief 数据目录 */
typedef struct DataDirectory
{
	char ref[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 数据引用 */
	char FC[3];									/*!< 功能约束 */
} DataDirectory;

/*\brief 数据目录列表 */
typedef struct DataDirectoryList
{
	U32 size;					/*!< 数据数量 */
	DataDirectory* dataDirs;	/*!< 服务目录列表。内容为 struct #DataDirectory 的数组，元素数量由 size 成员指定 */
} DataDirectoryList;

/*\brief 文件条目信息 */
typedef struct FileEntry
{
	char fileName[VISIBLE_STRING_129_LEN + 1];	/*!< 文件名 */
	U32 fileSize;								/*!< 文件大小。单位为字节 */
	IEC61850_TimeStamp lastModifiedTime;		/*!< 最后的修改时间 */
	U32 checkSum;								/*!< 校验和是文件数据的 CRC32 校验码，其生成多项式采用 0x04C11DB7 */
} FileEntry;

/*\brief 文件条目列表 */
typedef struct FileEntryList
{
	U32 size;				/*!< 文件条目数量 */
	FileEntry* fileEntries;	/*!< 文件条目列表。内容为 struct #FileEntry 的数组，元素数量由 size 成员指定 */
} FileEntryList;

/*\brief CMS数据定义 */
typedef struct CMSDataDefinition
{
	eDataTypeCMS eDataType;							/*!< 数据类型 */
	eServiceError error;							/*!< 服务错误码 */
	int numOfStructOrArrayItems;					/*!< 数据数量。
					若数据类型 eDataType 为结构体类型，则代表结构体成员的数量；
					若数据类型 eDataType 为数组类型，则代表数据元素的数量 */
	char name[OBJECT_NAME_STRING_LEN + 1];			/*!< 定义名称 */
	char fc[FC_LEN + 1];	/*!< 功能约束 */
	unsigned int stringLength;						/*!< 定义名称长度 */
	struct CMSDataDefinition * dataDefinitions;		/*!< 子级数据定义 */
} CMSDataDefinition;

/*\brief RPC 接口的方法定义列表 */
typedef struct MethodList
{
	unsigned int length;		/*!< 响应结果的数量 */
	struct tMethod* methods;	/*!< 设置多播采样值控制块值的响应结果列表。
								内容为 struct tMethod 的数组，元素数量由 length 成员指定 */
} MethodList;

/*! \brief 接口类型定义结构体 */
typedef struct tInterface
{
	char* name;				/*!< 接口名称(以null结尾的字符串) */
	MethodList* methodList;	/*!< 接口方法集合指针 */
} tInterface;

/*! \brief 接口列表容器结构体 */
typedef struct InterfaceList
{
	unsigned int numOfInterfaces;	/*!< 当前包含的接口数量 */
	tInterface* interfaces;			/*!< 接口数组指针(动态内存分配) */
} InterfaceList;


/*!\brief RPC 接口方法定义（不含名称和函数地址） */
typedef struct MethodDefinition
{
	unsigned int version;			/*!< 版本号 */
	unsigned int timeout;			/*!< 超时时间 */
	CMSDataDefinition* request;		/*!< 请求参数定义 */
	CMSDataDefinition* response;	/*!< 响应参数定义 */
} MethodDefinition;

/*!\brief 读远程过程调用方法定义的响应结果 */
typedef struct GetRpcMethodDefinitionResult
{
	int resultError;					/*!< 服务错误。
											实际值为 #eServiceError 。
											读远程过程调用方法定义成功时，该值为 #SERVICE_ERROR_NO_ERROR (0：无差错)，否则为非 0 值的 #eServiceError */
	MethodDefinition* methodDefinition;	/*!< 读远程过程调用方法定义的响应结果。读远程过程调用方法定义成功时，该值有效，否则为 NULL */
} GetRpcMethodDefinitionResult;

/*!\brief 读远程过程调用方法定义的响应结果列表 */
typedef struct GetRpcMethodDefinitionResultList
{
	unsigned int numOfResults;		/*!< 响应结果的数量 */
	GetRpcMethodDefinitionResult* getRpcMethodDefinitionResults;	/*!< 读远程过程调用方法定义的响应结果列表。
									内容为 struct GetRpcMethodDefinitionResult 的数组，元素数量由 numOfResults 成员指定 */
} GetRpcMethodDefinitionResultList;

/*! \brief RPC通信数据包结构体 */
typedef struct RpcData
{
	eDataTypeCMS eDataType;	/*!< 数据格式类型(枚举值) */
	int index;				/*!< 数据索引标识符 */
	unsigned int bitSize;	/*!< 数据位长度(单位：bit) */
	void* pvData;			/*!< 数据内容指针(需根据eDataType解析) */
} RpcData;


/*!	\brief	远程过程调用（RPC）方法函数。
	<p>
		用于远程过程调用服务，是远程过程调用接口方法的实体函数类型。
	</p>
	\param[in]	reqData	RPC请求数据
	\param[out]	rspData	RPC响应数据
*/
typedef void (*CMS_RpcCallFunc)(RpcData* reqData, RpcData* rspData);

/*\brief RPC 接口方法定义 */
typedef struct tMethod
{
	char* name;							/*!< 方法名称 */
	unsigned int version;				/*!< 版本号 */
	unsigned int timeout;				/*!< 超时时间 */
	struct CMSDataDefinition request;	/*!< 请求参数定义 */
	struct CMSDataDefinition response;	/*!< 响应参数定义 */
	CMS_RpcCallFunc function;			/*!< 方法的函数地址 */
} tMethod;

/*!\brief ACSI 服务接口 GetServerDirectory 的请求数据 */
typedef struct GetServerDirectory_Request
{
	int objectClass;				/*!< 对象类别。该值应始终指定为 1 (代表 logical-device)，不应指定为其他值。 */
	char* referenceAfter;			/*!< 对象引用。代表请求应响应该对象之后的对象。 */
}GetServerDirectory_Request;

/*!\brief ACSI 服务接口 GetServerDirectory 的响应数据 */
typedef struct GetServerDirectory_Response
{
	eServiceError serviceError;		/*!< 服务错误码 */
	StringList* reference;			/*!< 逻辑设备引用列表 */
	Boolean moreFollows;			/*!< moreFollows。<br>
										值为 FALSE 代表当次请求已返回与指定参数对应的全部内容；<br>
										值为 TRUE 代表当次请求的响应数据之后还有内容没有返回。<br>
										如要获取后续内容，应根据档次返回的结果调整请求参数，并再次发起请求。<br>
										请求中可以指定 referenceAfter 参数的，通过 referenceAfter 参数的值来调整即可；<br>
										请求中不能指定 referenceAfter参数的，需要通过更换其他参数的值来调整。 */
}GetServerDirectory_Response;

/*!	\brief	ACSI 服务接口 GetLogicalDeviceDirectory 的请求数据 */
typedef struct GetLogicalDeviceDirectory_Request
{
	char* ldName;				/*!< 逻辑设备名称（LDName）。
									若模型文件中有给逻辑设备配置 LDName，则 LDName 为配置的名称(ldName)
									若模型文件中未给逻辑设备配置 LDName，则 LDName 是 "IED 名称(name) + 逻辑设备实例名称(inst) " */
	char* referenceAfter;		/*!< 这里是逻辑节点的引用（lnReference）
									用于请求指定的 lnReference 之后的信息。 */
}GetLogicalDeviceDirectory_Request;

/*!	\brief	ACSI 服务接口 GetLogicalDeviceDirectory 的响应数据	 */
typedef struct GetLogicalDeviceDirectory_Response
{
	eServiceError serviceError;		/*!< 服务错误码 */
	StringList* lnReference;		/*!< 逻辑节点LN引用集合 */
	Boolean moreFollows;			/*!< moreFollows。
									值为 FALSE 代表当次请求已返回与指定参数对应的全部内容；
									值为 TRUE 代表当次请求的响应数据之后还有内容没有返回。
									如要获取后续内容，应根据档次返回的结果调整请求参数，并再次发起请求。
									请求中可以指定 referenceAfter 参数的，通过 referenceAfter 参数的值来调整即可；
									请求中不能指定 referenceAfter参数的，需要通过更换其他参数的值来调整。 */
}GetLogicalDeviceDirectory_Response;

/*! \brief 逻辑节点目录查询请求结构体 */
typedef struct GetLogicalNodeDirectory_Request
{
	char* reference;					/*!< 目标逻辑节点引用路径(如"LD1/LLN0") */
	enum IEC61850_ACSIClass acsiClass;	/*!< ACSI服务类别(LOGICAL-DEVICE等) */
	char* referenceAfter;				/*!< 分页查询的起始位置标识(可为NULL) */
} GetLogicalNodeDirectory_Request;

/*! \brief 逻辑节点目录查询响应结构体 */
typedef struct GetLogicalNodeDirectory_Response
{
	eServiceError serviceError;	/*!< 服务错误码(SUCCESS/OBJECT-NOT-EXIST等) */
	StringList* reference;		/*!< 逻辑节点引用路径链表 */
	Boolean moreFollows;		/*!< 分页标志(TRUE表示还有后续数据) */
} GetLogicalNodeDirectory_Response;

/*! \brief 全数据查询请求结构体 */
typedef struct GetAllData_Request
{
	char* reference;		/*!< 目标数据对象引用路径 */
	char* fc;				/*!< 功能约束条件(ST/MX等) */
	char* referenceAfter;	/*!< 分页查询的起始位置标识 */
} GetAllData_Request;

/*! \brief 全数据值查询响应结构体 */
typedef struct GetAllDataValues_Response
{
	eServiceError serviceError;		/*!< 服务错误码 */
	U32 length;						/*!< 返回的数据项数量 */
	DataRefValue* dataRefValueList;	/*!< 数据引用-值对数组 */
	Boolean moreFollows;			/*!< 分页标志 */
} GetAllDataValues_Response;

/*! \brief 全数据定义查询响应结构体 */
typedef struct GetAllDataDefinition_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	DataDefinitions data;		/*!< 数据定义集合(包含类型/属性等元数据) */
	Boolean moreFollows;		/*!< 分页标志 */
} GetAllDataDefinition_Response;

/*! \brief 控制块值查询请求结构体 */
typedef struct GetAllCBValues_Request
{
	char* reference;					/*!< 目标控制块引用路径 */
	enum IEC61850_ACSIClass acsiClass;	/*!< 控制块类型(REPORT-CONTROL等) */
	char* referenceAfter;				/*!< 分页查询的起始位置标识 */
} GetAllCBValues_Request;

/*!	\brief	ACSI服务接口GetAllCBValues的响应数据结构 */
typedef struct GetAllCBValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码，参见#eServiceError枚举定义 */
	GetAllCBValsReturn cbValue;	/*!< 控制块值集合，参见#GetAllCBValsReturn结构定义 */
	Boolean moreFollows;		/*!< 是否还有后续数据标志
									TRUE表示还有更多数据待获取
									FALSE表示已返回全部数据 */
} GetAllCBValues_Response;

/*! \brief 数据值读取请求结构体 */
typedef struct GetDataValues_Request
{
	FCDAList data;	/*!< 功能约束数据属性列表(Functional Constraint Data Attribute) */
} GetDataValues_Request;

/*! \brief 数据值读取响应结构体 */
typedef struct GetDataValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码(SUCCESS/ACCESS-DENIED等) */
	DataValsList value;			/*!< 数据值链表(包含时间戳和品质信息) */
	Boolean moreFollows;		/*!< 分页标志(TRUE表示还有后续数据) */
} GetDataValues_Response;

/*! \brief 数据值写入请求结构体 */
typedef struct SetDataValues_Request
{
	U32 dataNum;		/*!< 待写入的数据项数量 */
	FCDAVals* fcdaVals;	/*!< 功能约束数据属性-值对数组 */
} SetDataValues_Request;

/*! \brief 数据值写入响应结构体 */
typedef struct SetDataValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	ServiceErrorList result;	/*!< 各数据项的详细错误信息列表 */
} SetDataValues_Response;

/*!	\brief	ACSI服务接口GetDataDirectory的请求数据结构 */
typedef struct GetDataDirectory_Request
{
	char* dataReference;	/*!< 数据对象引用路径 */
	char* referenceAfter;	/*!< 起始查询位置（返回该引用之后的数据）*/
}GetDataDirectory_Request;

/*!	\brief	ACSI服务接口GetDataDirectory的响应数据结构 */
typedef struct GetDataDirectory_Response
{
	eServiceError serviceError;			/*!< 服务错误码 */
	DataDirectoryList dataAttribute;	/*!< 数据目录列表，参见#DataDirectoryList */
	Boolean moreFollows;				/*!< 是否还有后续数据标志 */
}GetDataDirectory_Response;

/*!	\brief	ACSI服务接口GetDataDefinition的请求数据结构 */
typedef struct GetDataDefinition_Request
{
	FCDAList data;	/*!<  带功能约束的数据引用列表 */
}GetDataDefinition_Request;	

/*! \brief 数据定义查询响应结构体 */
typedef struct GetDataDefinition_Response
{
	eServiceError serviceError;	/*!< 服务错误码(SUCCESS/OBJECT-NOT-EXIST等) */
	DataDefinitions data;		/*!< 数据定义集合(包含类型/属性等元数据) */
	Boolean moreFollows;		/*!< 分页标志(TRUE表示还有后续数据) */
} GetDataDefinition_Response;

/*! \brief 数据集创建请求结构体 */
typedef struct CreateDataSet_Request
{
	char* datasetReference;	/*!< 数据集引用路径(如"LD1/LLN0$ds1") */
	char* referenceAfter;	/*!< 分页查询的起始位置标识 */
	FCDA* fcdaList;			/*!< 功能约束数据属性数组 */
	U32 numOfFcda;			/*!< FCDA数组元素数量 */
} CreateDataSet_Request;

/*! \brief 数据集删除请求结构体 */
typedef struct DeleteDataSet_Request
{
	char* datasetReference;	/*!< 待删除数据集引用路径 */
} DeleteDataSet_Request;

/*! \brief 数据集删除响应结构体 */
typedef struct DeleteDataSet_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
} DeleteDataSet_Response;

/*! \brief 数据集目录查询请求结构体 */
typedef struct GetDataSetDirectory_Request
{
	char* datasetReference;	/*!< 目标数据集引用路径 */
	char* referenceAfter;	/*!< 分页查询的起始位置标识 */
} GetDataSetDirectory_Request;

/*! \brief 数据集目录查询响应结构体 */
typedef struct GetDataSetDirectory_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	FCDAList memberData;		/*!< 数据集成员列表 */
	Boolean moreFollows;		/*!< 分页标志 */
} GetDataSetDirectory_Response;

/*! \brief 数据集值查询请求结构体 */
typedef struct GetDataSetValues_Request
{
	char* datasetReference;	/*!< 目标数据集引用路径 */
	char* referenceAfter;	/*!< 分页查询的起始位置标识 */
} GetDataSetValues_Request;

/*! \brief 数据集值查询响应结构体 */
typedef struct GetDataSetValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	DataValsList value;			/*!< 数据值链表(含时间戳和品质信息) */
	Boolean moreFollows;		/*!< 分页标志 */
} GetDataSetValues_Response;

/*! \brief 数据集值设置请求结构体 */
typedef struct SetDataSetValues_Request
{
	char* datasetReference;	/*!< 目标数据集引用路径 */
	char* referenceAfter;	/*!< 分页查询的起始位置标识 */
	DataValsList value;		/*!< 待设置的数据值链表 */
} SetDataSetValues_Request;

/*! \brief 数据集值设置响应结构体 */
typedef struct SetDataSetValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	ServiceErrorList result;	/*!< 各数据项的详细错误信息 */
} SetDataSetValues_Response;

/*! \brief 对象选择请求结构体 */
typedef struct Select_Request
{
	char reference[OBJECT_REFERENCE_STRING_LEN + 1];  /*!< 目标对象引用路径 */
} Select_Request;

/*! \brief 对象选择响应结构体 */
typedef struct Select_Response
{
	char reference[OBJECT_REFERENCE_STRING_LEN + 1];  /*!< 已选对象引用路径 */
} Select_Response;

/*! \brief 激活定值组请求结构体 */
typedef struct SelectActiveSG_Request
{
	char* sgcbReference;	/*!< SGCB控制块引用路径 */
	U8 settingGroupNumber;	/*!< 目标定值组编号(1~8) */
} SelectActiveSG_Request;

/*! \brief 激活定值组响应结构体 */
typedef struct SelectActiveSG_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
} SelectActiveSG_Response;

/*! \brief 编辑定值组请求结构体 */
typedef struct SelectEditSG_Request
{
	char* sgcbReference;	/*!< SGCB控制块引用路径 */
	U8 settingGroupNumber;	/*!< 目标定值组编号 */
} SelectEditSG_Request;

/*! \brief 编辑定值组响应结构体 */
typedef struct SelectEditSG_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
} SelectEditSG_Response;

/*! \brief 设置编辑定值请求结构体 */
typedef struct SetEditSGValue_Request
{
	IEC61850_DataAttributeValues data;	/*!< 定值数据属性集合 */
} SetEditSGValue_Request;

/*! \brief 设置编辑定值响应结构体 */
typedef struct SetEditSGValue_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	ServiceErrorList result;	/*!< 各定值的详细错误信息 */
} SetEditSGValue_Response;

/*! \brief 确认编辑定值请求结构体 */
typedef struct ConfirmEditSGValues_Request
{
	char* sgcbReference;	/*!< SGCB控制块引用路径 */
} ConfirmEditSGValues_Request;

/*! \brief 确认编辑定值响应结构体 */
typedef struct ConfirmEditSGValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
} ConfirmEditSGValues_Response;

/*! \brief 获取编辑定值请求结构体 */
typedef struct GetEditSGValue_Request
{
	FCDAList data;	/*!< 功能约束数据属性列表 */
} GetEditSGValue_Request;

/*! \brief 获取编辑定值响应结构体 */
typedef struct GetEditSGValue_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	DataValsList value;			/*!< 定值数据链表 */
	Boolean moreFollows;		/*!< 分页标志 */
} GetEditSGValue_Response;

/*! \brief SGCB值查询请求结构体 */
typedef struct GetSGCBValues_Request
{
	StringList* sgcbReference;	/*!< SGCB控制块引用路径链表 */
} GetSGCBValues_Request;

/*! \brief SGCB值查询响应结构体 */
typedef struct GetSGCBValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	SGCBValuesList sgcb;		/*!< SGCB控制块状态信息列表 */
	Boolean moreFollows;		/*!< 分页标志 */
} GetSGCBValues_Response;

/*!	\brief	报告控制块的值 */
typedef struct tSetBRCBValues
{
	char* reference;	/*!< 报告控制块引用 */
	char* rptId;		/*!< 报告控制块的ID */
	Boolean* rptEna;	/*!< 使能标记	TRUE：使能	FALSE：未使能 */
	U8* datSet;			/*!< 控制块关联的数据集引用 */
	U16* optFlds;		/*!< 可选域 */
	U32* bufTm;			/*!< 缓存时间。对于 BRCB，bufTm 应该为大于 0 的值；对于 URCB，bufTm 应始终为 0 值。 */
	U8* trgOps;			/*!< 触发条件 */
	U32* intgPd;		/*!< 完整性周期 */
	Boolean* gi;		/*!< 总召唤标记。设置该标记为 TRUE，用于触发总召唤 */
	Boolean* purgeBuf;	/*!< 清空报告缓存标记。仅对 BRCB 有效。设置该标记为 TRUE，用于清空报告缓存 */
	U8* entryId;		/*!< 条目 ID。仅对 BRCB 有效 */
	U16* resvTms;		/*!< 保留时间。仅对 BRCB 有效。resvTms > 0：客户端已占用 resvTms = 0：未占用 */
} tSetBRCBValues;

/*! \brief URCB(非缓冲报告控制块)参数设置结构体 */
typedef struct tSetURCBValues
{
	char* reference;	/*!< 控制块引用路径(如"LD1/LLN0.URCB01") */
	char* rptId;		/*!< 报告标识符(最大64字节) */
	Boolean* rptEna;	/*!< 报告使能标志(TRUE/FALSE) */
	U8* datSet;			/*!< 关联数据集引用(可变长度字符串) */
	U16* optFlds;		/*!< 可选字段配置位掩码 */
	U32* bufTm;			/*!< 缓冲时间(毫秒) */
	U8* trgOps;			/*!< 触发条件位掩码 */
	U32* intgPd;		/*!< 完整性周期(毫秒) */
	Boolean* gi;		/*!< 总召标志(TRUE触发立即上报) */
	Boolean* resv;		/*!< 保留字段(对齐填充) */
} tSetURCBValues;


/*!	\brief	设置缓存报告控制块值的响应结果	 */
typedef struct tSetBRCBErrors
{
	eServiceError setError;			/*!< 无差错 */
	eServiceError setRptIDError;	/*!< 设置报告 */
	eServiceError setRptEnaError;	/*!< 设置报告使能 */
	eServiceError setDataSetError;	/*!< 设置数据集 */
	eServiceError setOptFldsError;	/*!< 设置可选域 */
	eServiceError setBufTmError;	/*!< 设置缓存时间 */
	eServiceError setTrgOpsError;	/*!< 设置触发条件 */
	eServiceError setIntgPdError;	/*!< 设置完整性周期 */
	eServiceError setGIError;		/*!< 设置总召 */
	eServiceError setPurgeBufError;	/*!< 设置清除缓存 */
	eServiceError setEntryIDError;	/*!< 设置实体编号 */
	eServiceError setResvTmsError;	/*!< 设置预设值 */
}tSetBRCBErrors;

/*!	\brief	设置非报告控制块值的响应结果	 */
typedef struct tSetURCBErrors
{
	eServiceError setError;			/*!< 无差错 */
	eServiceError setRptIDError;	/*!< 设置报告ID */
	eServiceError setRptEnaError;	/*!< 设置报告使能 */
	eServiceError setDataSetError;	/*!< 设置数据集 */
	eServiceError setOptFldsError;	/*!< 设置可选域 */
	eServiceError setBufTmError;	/*!< 设置缓存时间 */
	eServiceError setTrgOpsError;	/*!< 设置触发条件 */
	eServiceError setIntgPdError;	/*!< 设置完整性周期 */
	eServiceError setGIError;		/*!< 设置总召 */
	eServiceError setResvError;		/*!< 设置预设值 */
}tSetURCBErrors;

/*! \brief 缓存报告控制块(BRCB)查询请求结构体 */
typedef struct GetRCBValues_Request
{
	char** reference;		/*!< 控制块引用路径数组 */
	unsigned int number;	/*!< 请求的控制块数量 */
} GetBRCBValues_Request;

/*! \brief 缓存报告控制块(BRCB)查询响应结构体 */
typedef struct GetRCBValues_Response
{
	eServiceError serviceError;		/*!< 服务错误码 */
	ReturnRCBValues* returnList;	/*!< 返回的控制块值列表 */
	unsigned int numberOfCBs;		/*!< 实际返回的控制块数量 */
	Boolean moreFollows;			/*!< 分页标志(TRUE表示还有数据) */
} GetBRCBValues_Response;

/*! \brief 缓存报告控制块(BRCB)设置请求结构体 */
typedef struct SetBRCBValues_Request
{
	unsigned int numOfRptCB;		/*!< 待设置的控制块数量 */
	tSetBRCBValues* brcbValsList;	/*!< BRCB参数设置值数组 */
} SetBRCBValues_Request;

/*! \brief 缓存报告控制块(BRCB)设置响应结构体 */
typedef struct SetBRCBValues_Response
{
	eServiceError serviceError;		/*!< 服务错误码 */
	unsigned int numOfRptCB;		/*!< 成功设置的控制块数量 */
	tSetBRCBErrors* setRCBErrsList;	/*!< 各控制块设置错误详情 */
} SetBRCBValues_Response;

/*! \brief 非缓存报告控制块(URCB)请求类型定义 */
typedef struct GetRCBValues_Request GetURCBValues_Request;

/*! \brief 非缓存报告控制块(URCB)响应类型定义 */
typedef struct GetRCBValues_Response GetURCBValues_Response;

/*! \brief URCB参数批量设置请求结构体 */
typedef struct SetURCBValues_Request
{
	unsigned int numOfRptCB;		/*!< 待设置的URCB控制块数量 */
	tSetURCBValues* urcbValsList;	/*!< URCB参数数组指针 */
} SetURCBValues_Request;

/*! \brief URCB参数批量设置响应结构体 */
typedef struct SetURCBValues_Response
{
	eServiceError serviceError;		/*!< 服务错误码 */
	unsigned int numOfRptCB;		/*!< 实际完成设置的URCB数量 */
	tSetURCBErrors* setRCBErrsList;	/*!< 详细错误列表 */
} SetURCBValues_Response;


/*! \brief 日志控制块(LCB)查询请求结构体 */
typedef struct GetLCBValues_Request
{
	char** reference;		/*!< 日志控制块引用路径数组 */
	unsigned int number;	/*!< 请求的日志控制块数量 */
} GetLCBValues_Request;

/*! \brief 日志控制块(LCB)查询响应结构体 */
typedef struct GetLCBValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	LCBValuesList lcb;			/*!< 返回的日志控制块值列表 */
	Boolean moreFollows;		/*!< 分页标志 */
} GetLCBValues_Response;

/*! \brief 日志控制块(LCB)设置请求结构体 */
typedef struct SetLCBValues_Request
{
	tSetLcbValuesList lcb;	/*!< LCB参数列表，包含：
							- logRef: 日志控制块引用路径
							- logEna: 日志使能状态
							- trgOps: 触发条件位掩码 */
} SetLCBValues_Request;

/*! \brief 日志控制块(LCB)设置响应结构体 */
typedef struct SetLCBValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	SetLCBErrorList result;		/*!< 详细错误列表，包含每个LCB的设置结果 */
} SetLCBValues_Response;

/*! \brief 按时间范围查询日志请求结构体 */
typedef struct QueryLogByTime_Request
{
	char* logReference;				/*!< 日志控制块引用路径 */
	IEC61850_TimeStamp* startTime;	/*!< 查询起始时间(UTC格式) */
	IEC61850_TimeStamp* stopTime;	/*!< 查询结束时间 */
	U64* entryAfter;				/*!< 起始条目ID(可选) */
} QueryLogByTime_Request;

/*! \brief 按时间范围查询日志响应结构体 */
typedef struct QueryLogByTime_Response
{
	eServiceError serviceError;		/*!< 服务错误码 */
	IEC61850_LogEntries logEntry;	/*!< 返回的日志条目集合 */
	Boolean moreFollows;			/*!< 分页标志(TRUE表示还有数据) */
} QueryLogByTime_Response;

/*! \brief 按条目ID查询日志请求结构体 */
typedef struct QueryLogAfter_Request
{
	char* logReference;				/*!< 日志控制块引用路径 */
	IEC61850_TimeStamp* startTime;	/*!< 时间参考点(可选) */
	U64 entry;						/*!< 起始条目ID */
} QueryLogAfter_Request;

/*! \brief 按条目ID查询日志响应结构体 */
typedef struct QueryLogAfter_Response
{
	eServiceError serviceError;		/*!< 服务错误码 */
	IEC61850_LogEntries logEntry;	/*!< 返回的日志条目集合 */
	Boolean moreFollows;			/*!< 数据分页标志：
										- TRUE: 还有后续数据
										- FALSE: 最后一批数据 */
} QueryLogAfter_Response;

/*! \brief 日志状态批量查询请求结构体 */
typedef struct GetLogStatusValues_Request
{
	char** reference;		/*!< 日志控制块引用路径数组指针，每个元素格式为：
								"LDName/LNName\.LogName" */
	unsigned int number;	/*!< 待查询的日志控制块数量 */
} GetLogStatusValues_Request;


/*! \brief 日志状态查询响应结构体 */
typedef struct GetLogStatusValues_Response
{
	eServiceError serviceError;				/*!< 服务错误码 */
	IEC61850_GetLogStatus_ResultList log;	/*!< 日志状态信息列表 */
	Boolean moreFollows;					/*!< 分页标志 */
} GetLogStatusValues_Response;


/*! \brief GOOSE控制块引用查询请求结构体 */
typedef struct GetGoReference_Request
{
	char gocbReference[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< GOOSE控制块引用路径 */
	U32 memberOffsetNum;									/*!< 成员偏移量数量 */
	GoCBMemberOffsetList memberOffset;						/*!< 成员偏移量列表 */
} GetGoReference_Request;

/*! \brief GOOSE控制块引用查询响应结构体 */
typedef struct GetGoReference_Response
{
	eServiceError serviceError;								/*!< 服务错误码 */
	char gocbReference[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 返回的GOOSE控制块引用 */
	U32 confRev;											/*!< 配置版本号 */
	char datSet[OBJECT_REFERENCE_STRING_LEN + 1];			/*!< 关联的数据集引用 */
	FCDAList memberData;									/*!< 功能约束数据属性列表 */
} GetGoReference_Response;

/*! \brief GOOSE元素编号查询请求结构体 */
typedef struct GetGOOSEElementNumber_Request
{
	char gocbReference[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< GOOSE控制块引用路径 */
	FCDAList memberData;									/*!< 功能约束数据属性列表 */
} GetGOOSEElementNumber_Request;

/*! \brief GOOSE元素编号查询响应结构体 */
typedef struct GetGOOSEElementNumber_Response
{
	eServiceError serviceError;								/*!< 服务错误码 */
	char gocbReference[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< GOOSE控制块引用路径 */
	U32 confRev;											/*!< 配置版本号 */
	char datSet[OBJECT_REFERENCE_STRING_LEN + 1];			/*!< 关联的数据集引用 */
	GoCBMemberOffsetList memberOffset;						/*!< 成员偏移量列表 */
} GetGOOSEElementNumber_Response;

/*! \brief GOOSE控制块值批量查询请求结构体 */
typedef struct GetGoCBValues_Request
{
	char** reference;		/*!< GOOSE控制块引用路径数组 */
	unsigned int number;	/*!< 查询的GOOSE控制块数量 */
} GetGoCBValues_Request;

/*! \brief GOOSE控制块值批量查询响应结构体 */
typedef struct GetGoCBValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	GoCBValuesList gocb;		/*!< GOOSE控制块值列表 */
	Boolean moreFollows;		/*!< 是否还有更多数据标志 */
} GetGoCBValues_Response;

/*! \brief GOOSE控制块值设置请求结构体 */
typedef struct SetGoCBValues_Request
{
	unsigned int number;	/*!< 要设置的GOOSE控制块数量 */
	tSetGoCBValues* list;	/*!< GOOSE控制块设置参数列表 */
} SetGoCBValues_Request;

/*! \brief GOOSE控制块值设置响应结构体 */
typedef struct SetGoCBValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	SetGocbErrorList result;	/*!< 设置结果列表 */
} SetGoCBValues_Response;


/*! \brief 多播采样值控制块查询请求结构体 */
typedef struct GetMSVCBValues_Request
{
	char** reference;		/*!< MSVCB控制块引用路径数组 */
	unsigned int number;	/*!< 查询的MSVCB控制块数量 */
} GetMSVCBValues_Request;

/*! \brief 多播采样值控制块查询响应结构体 */
typedef struct GetMSVCBValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	MSVCBValuesList msvcb;		/*!< 返回的采样值控制块列表 */
	Boolean moreFollows;		/*!< 分页标志：TRUE表示还有后续数据 */
} GetMSVCBValues_Response;

/*! \brief 多播采样值控制块设置请求结构体 */
typedef struct SetMSVCBValues_Request
{
	unsigned int length;	/*!< 要设置的MSVCB控制块数量 */
	tSetMSVCBValues* list;	/*!< MSVCB控制块设置参数数组 */
} SetMSVCBValues_Request;

/*! \brief 多播采样值控制块设置响应结构体 */
typedef struct SetMSVCBValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	SetMSVCBErrorList result;	/*!< 设置结果明细列表 */
} SetMSVCBValues_Response;

/*! \brief 文件获取请求结构体 */
typedef struct GetFile_Request
{
	char* fileName;		/*!< 目标文件名(含路径) */
	U32 startPostion;	/*!< 读取起始位置(字节偏移) */
} GetFile_Request;

/*! \brief 文件获取响应结构体 */
typedef struct GetFile_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	U32 fileDataLen;			/*!< 返回的文件数据长度 */
	char* fileData;				/*!< 文件数据缓冲区指针 */
	Boolean endOfFile;			/*!< 文件结束标志 */
} GetFile_Response;

/*! \brief 文件写入请求结构体 */
typedef struct SetFile_Request
{
	char* fileName;		/*!< 目标文件名(含路径) */
	U32 startPostion;	/*!< 写入起始位置 */
	U32 fileDataLen;	/*!< 写入数据长度 */
	char* fileData;		/*!< 待写入数据缓冲区 */
	Boolean endOfFile;	/*!< 文件结束标志 */
} SetFile_Request;

/*! \brief 文件写入响应结构体 */
typedef struct SetFile_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
} SetFile_Response;

/*! \brief 文件属性查询请求结构体 */
typedef struct GetFileAttributeValues_Request
{
	char fileName[VISIBLE_STRING_255_LEN + 1];	/*!< 目标文件名(最大255字符) */
} GetFileAttributeValues_Request;

/*! \brief 文件属性查询响应结构体 */
typedef struct GetFileAttributeValues_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	FileEntry fileEntries;		/*!< 文件属性条目 */
} GetFileAttributeValues_Response;

/*! \brief 目录查询请求结构体 */
typedef struct GetFileDirectory_Request
{
	char pathName[VISIBLE_STRING_255_LEN + 1];	/*!< 查询路径(最大255字符) */
	IEC61850_TimeStamp* startTime;				/*!< 时间范围起始(UTC时间戳) */
	IEC61850_TimeStamp* stopTime;				/*!< 时间范围结束(UTC时间戳) */
	char* fileAfter;							/*!< 分页查询的起始文件名 */
} GetFileDirectory_Request;

/*! \brief 目录查询响应结构体 */
typedef struct GetFileDirectory_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	FileEntryList fileEntries;	/*!< 文件条目列表 */
	Boolean moreFollows;		/*!< 分页标志：TRUE表示还有后续数据 */
} GetFileDirectory_Response;


/*! \brief RPC接口目录查询请求结构体 */
typedef struct GetRpcInterfaceDirectory_Request
{
	char* referenceAfter;	/*!< 分页查询起始位置标识符 */
} GetRpcInterfaceDirectory_Request;

/*! \brief RPC接口目录查询响应结构体 */
typedef struct GetRpcInterfaceDirectory_Response
{
	eServiceError serviceError;		/*!< 服务错误码 */
	struct StringList reference;	/*!< 接口名称列表 */
	Boolean moreFollows;			/*!< 分页标志：TRUE表示还有更多数据 */
} GetRpcInterfaceDirectory_Response;

/*! \brief RPC方法目录查询请求结构体 */
typedef struct GetRpcMethodDirectory_Request
{
	char* sInterface;		/*!< 目标接口名称 */
	char* referenceAfter;	/*!< 分页查询起始位置标识符 */
} GetRpcMethodDirectory_Request;

/*! \brief RPC方法目录查询响应结构体 */
typedef struct GetRpcMethodDirectory_Response
{
	eServiceError serviceError;		/*!< 服务错误码 */
	struct StringList reference;	/*!< 方法名称列表 */
	Boolean moreFollows;			/*!< 分页标志：TRUE表示还有更多数据 */
} GetRpcMethodDirectory_Response;

/*! \brief RPC接口定义查询请求结构体 */
typedef struct GetRpcInterfaceDefinition_Request
{
	char* sInterface;		/*!< 目标接口名称 */
	char* referenceAfter;	/*!< 分页查询起始位置标识符 */
} GetRpcInterfaceDefinition_Request;

/*! \brief RPC接口定义查询响应结构体 */
typedef struct GetRpcInterfaceDefinition_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	MethodList method;			/*!< 方法定义列表 */
	Boolean moreFollows;		/*!< 分页标志：TRUE表示还有更多数据 */
} GetRpcInterfaceDefinition_Response;

/*! \brief RPC方法定义查询请求结构体 */
typedef struct GetRpcMethodDefinition_Request
{
	struct StringList reference;	/*!< 方法引用列表 */
} GetRpcMethodDefinition_Request;

/*! \brief RPC方法定义查询响应结构体 */
typedef struct GetRpcMethodDefinition_Response
{
	eServiceError serviceError;					/*!< 服务错误码 */
	GetRpcMethodDefinitionResultList reference;	/*!< 方法定义结果列表 */
	Boolean moreFollows;						/*!< 分页标志：TRUE表示还有更多数据 */
} GetRpcMethodDefinition_Response;

/*! \brief RPC调用请求结构体 */
typedef struct RpcCall_Request
{
	char* method;		/*!< 目标方法名称 */
	RpcData reqData;	/*!< 请求参数数据 */
	U8* callID;			/*!< 调用标识符(用于异步调用) */
} RpcCall_Request;

/*! \brief RPC调用响应结构体 */
typedef struct RpcCall_Response
{
	eServiceError serviceError;	/*!< 服务错误码 */
	RpcData rspData;			/*!< 响应结果数据 */
	U8* nextCallID;				/*!< 下一次调用标识符 */
} RpcCall_Response;


/*! \brief 控制状态枚举 */
typedef enum eControlState
{
	CONTROL_STATE_DISABLED,					/*!< 控制功能禁用状态 */
	CONTROL_STATE_UNSELECTED,				/*!< 控制点未被选中状态 */
	CONTROL_STATE_READY,					/*!< 控制点就绪状态 */
	CONTROL_STATE_WAIT_FOR_CHANGE,			/*!< 等待状态变化确认 */
	CONTROL_STATE_WAIT_FOR_ACTIVATION_TIME,	/*!< 等待激活时间到达 */
} eControlState;

/*! \brief 控制信息结构体 */
typedef struct ControlInfo
{
	int     currentState;		/*!< 当前控制状态 */
	U32     stVal;				/*!< 状态值 */
	U8      stValType;			/*!< 状态值类型 */
	U8      stValSize;			/*!< 状态值大小(字节) */
	U32     ctlVal;				/*!< 控制值 */
	U8      ctValType;			/*!< 控制值类型 */
	U8      ctlValSize;			/*!< 控制值大小(字节) */
	unsigned char OrCat;		/*!< 控制源类别 */
	unsigned char OrIdent[CONTROL_ORIGIN_IDENT_SIZE];	/*!< 控制源标识 */
	unsigned char OrIdentSize;	/*!< 控制源标识长度 */
	U8      controlNumber;		/*!< 控制序号 */
	unsigned char Time[CONTROL_TIME_SIZE];	/*!< 时间戳 */
	unsigned char Test;			/*!< 测试模式标志 */
	unsigned char Check;		/*!< 校验标志 */
	U8      operTime[CONTROL_TIME_SIZE];	/*!< 操作时间 */
} ControlInfo;

/*! \brief 数据集数据结构体 */
typedef struct IEC61850_DatasetData
{
	IEC61850_DataAttributeData data;	/*!< 数据属性值 */
	char dataReference[OBJECT_REFERENCE_STRING_LEN + 1];	/*!< 数据引用路径 */
	unsigned int dataIndexInDataset;	/*!< 在数据集中的索引 */
	IEC61850_DataAttributeID* daid;		/*!< 数据属性ID指针 */
	char* sAddr;						/*!< 短地址 */
} IEC61850_DatasetData;

/*! \brief 控制块数据列表结构体 */
typedef struct IEC61850_ControlBlockDataList
{
	IEC61850_DatasetData* datasetDatas;	/*!< 数据集数据数组 */
	unsigned int numOfDatas;			/*!< 数据项数量 */
} IEC61850_ControlBlockDataList;

/*!	\brief	数据集数据列表 */
typedef struct IEC61850_ControlBlockDataList IEC61850_DataSetDataList;

/*!	\brief	数据携带对应q和t的结构体数据 */
typedef struct IEC61850_DataAttributeDataQT
{
	IEC61850_DataAttributeData	dataVal;	/*!< 数据值 */
	tIEC61850Quality*			q;			/*!< 质量 */
	IEC61850_TimeStamp*			t;			/*!< 时间 */
} IEC61850_DataAttributeDataQT;

/*! \brief 关联参数结构体（ACSE层参数） */
typedef struct IEC61850_AssociationParameters
{
	char calledAPTitle[32];		/*!< 被叫AP标题（应用进程标识） */
	S32 calledAEQualifier;		/*!< 被叫AE限定符（应用实体标识） */
	U32 calledPSelect;			/*!< 被叫表示层选择器 */
	U16 calledSSelect;			/*!< 被叫会话层选择器 */
	U16 calledTSelect;			/*!< 被叫传输层选择器 */

	char callingAPTitle[32];	/*!< 主叫AP标题（应用进程标识） */
	S32 callingAEQualifier;		/*!< 主叫AE限定符（应用实体标识） */
	U32 callingPSelect;			/*!< 主叫表示层选择器 */
	U16 callingSSelect;			/*!< 主叫会话层选择器 */
	U16 callingTSelect;			/*!< 主叫传输层选择器 */

	char IPAddress[16];			/*!< 服务器IP地址（IPv4格式） */
	U16 port;					/*!< 服务器TCP端口号 */
	char* authPassword;			/*!< ACSE认证密码（NULL表示无认证） */
} IEC61850_AssociationParameters;

/*! \brief 远程控制参数结构体 */
typedef struct IEC61850_ControlRemote
{
	char domain[129];			/*!< 逻辑设备域名 */
	char itemName[129];			/*!< 控制项名称 */
	char reference[129];		/*!< 数据对象引用路径 */
	char ctlType;				/*!< 控制数据类型（如BOOLEAN/INTEGER等） */
	unsigned int ctlSize;		/*!< 控制数据大小（字节数） */
	unsigned int ctlNum;		/*!< 控制序号（用于SBO选择-操作序列） */
	unsigned char orCat;		/*!< 控制源类别（操作员/自动/调度等） */
	char orIdent[BYTES_64];		/*!< 控制源标识（64字节OCTET字符串） */
	unsigned char orIdentSize;	/*!< 控制源标识实际使用长度 */
} IEC61850_ControlRemote;


#ifdef __cplusplus
}
#endif

#endif
